笔者能力有限,目前就补了abc。
A:
对于
- c 是 a 的倍数,且 c>a。
- gcd(a,b)=gcd(b,c)。
对于这两个条件,打破了笔者想着只要等于a就可以的小心思。。。毕竟这不是小白赛。所以我们可以开始先把第二个条件变成:a和b已经互质,而且b和c也互质,而且c是a的倍数。为什么可以这样变化呢,因为我们可以两边同除原gcd(a,b)的值,让他们都变成互质,即设u=gcd(a,b)。
gcd(a/u,b/u)=gcd(b/u,c/u)成立,那么我们可以很容易得知c/a的倍数与b也是互质,不然的话这个gcd不会为1,那么我们的条件就变成了只要找到能够与b/u互质的最小数字就行了。那么,代码如下:
#includeusing namespace std; #define int long long int c[20]={2,3,5,7,11,13,17,19,23,29,31,37,41};//为什么只要到41呢,因为到41的连乘已经比1e14大 int d[100]; signed main(){ int t; cin>>t; while(t--){ int a,b; cin>>a>>b; int u=__gcd(a,b); b/=u; for(int i=0;i<=12;i++) if(b%c[i]!=0){ printf("%lldn",c[i]*a); break; } } }
B:
如果想知道解法的话,那么去看牛客的题解,他会很明确的告诉你就是一个普通的很暴力的暴力。就是点对们相加看看这个值会不会出现第二次。为什么可以这么做呢,为什么这样做时间复杂度不会超时呢?很简单的一个想法,因为我们把点对全部都加起来的话,总共可能出现的值只有可能是4*n*m个,不然的话就会出现新的覆盖点,被覆盖了我们就可以提前终止了。
代码如下:
#includeusing namespace std; #define int long long int mp[2005][2005]; struct node{ int x,y; }a[100005]; signed main(){ ios::sync_with_stdio(false); int t; cin>>t; while(t--){ int n,m,k; cin>>n>>m>>k; for(int i=1;i<=2*n;i++) for(int j=1;j<=2*m;j++) mp[i][j]=0; for(int i=1;i<=k;i++) cin>>a[i].x>>a[i].y; int flag=0; for(int i=1;i<=k;i++){ for(int j=i+1;j<=k;j++){ if(mp[a[i].x+a[j].x][a[i].y+a[j].y]){ flag=1,printf("YES %.1lf %.1lfn",(a[i].x+a[j].x)*1.0/2,(a[i].y+a[j].y)*1.0/2); break; } mp[a[i].x+a[j].x][a[i].y+a[j].y]=1; } if(flag) break; } if(flag==0) printf("NOn"); } }
C:
当你位于第 x个格子时,你可以进行以下两种操作:
- 走到第 x+1 个格子。
- 如果第 x 个格子未被染上色,把第 x 个格子染成黑色,然后跳到第 Ai 个格子。
对于一段区域即1-x(1<=x<=n)
如果最后落脚点是x的话,那么我们可能的转移方向就是从第x-1个转移过来的,没有意外。
如果最后落脚点不是x的话,我们可以选择Ax-(x-1)的任意一个数字作为最终落脚点,为什么呢,因为Ax到x-1这几个地方都可以由最后一个数字跳到Ax之后用1操作执行。
因为1-x这一段我们总共有f[x-1]*(x-Ax+1)种方法跳
因为1-1的时候,只能选择跳1,所以没地方跳,因此它的次数是1次,因此可以先进行初始化
代码如下:
#includeusing namespace std; #define int long long int a[1000005]; int f[1000005]; int p=1e9+7; signed main(){ ios::sync_with_stdio(false); int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; f[1]=1;//如果说只有1个的话,那肯定是只能移动一次 for(int i=2;i<=n;i++){ f[i]=f[i-1]*(i-a[i]+1)%p; } cout<



