题目链接:Problem - C - Codeforces Di-visible Confusion
给你一个长度为 n n n的序列,你可以从其中选一个下标 i i i,如果 a i m o d ( i + 1 ) a_i mod (i+1) aimod(i+1)!= 0 0 0,那么我们可以去掉它,之后的操作都是在之前的操作的结果上进行操作的。你需要判断能不能通过这个操作把整个序列删除。不难发现,对于第下标1,只能对2进行取模判断,对于下标2,可以对2和3进行取模判断,所以对于下标 n n n,可以对2,3,…,n+1进行取模判断。同时还发现,如果我们首先删除了第一个下标,会影响后面每一个取模,所以我们并不能从头开始删除,但是我们发现前面的删除不会受后面的删除影响,也就是说,前面判断可以去掉,并不会影响后面的判断。所以我们只需从头到尾的遍历一遍即可。
这道题的重点是如何维护,判断一个数能不能对 n n n个数都能整除,就是判断这个数是不是这 n n n个数的最小公倍数的倍数。最小公倍数可以通过gcd来求,打个表就行。需要注意的一个细节是,打表数据最后会非常大,大到一定的时候是一定成立的。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int T,n;
long long a[N];
long long gcd(long long x,long long y){
return y>0?gcd(y,x%y):x;
}
signed main(){
a[1]=2;
for(int i=2;i<=100000;i++){
if(a[i-1]>1e9){
a[i]=a[i-1];
}
else a[i]=a[i-1]*(i+1)/gcd(a[i-1],i+1);
//printf("%lld\n",a[i]);
}
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);
int flag=1;
for(int i=1,x;i<=n;i++){
scanf("%lld",&x);
if(flag==0) continue;
if(a[i]<=x&&x%a[i]==0){
flag=0;
}
}
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}
这道题,1e5打表少打一个0,re两发,寄。。。