题目大意
给一个长度为 n n n 的序列 a a a,对于每个位置 i i i,如果 a i m o d ( i + 1 ) ≠ 0 a_i \bmod (i+1)\ne0 aimod(i+1)=0,就可以将 a i a_i ai 删掉。
删掉之后,后面的数都会往前面移动一位。
问能否将序列删成空。
对于 100 % 100\% 100% 的数据, 1 ≤ t ≤ 1 0 4 , 1 ≤ n ≤ 1 0 5 , 1 ≤ ∑ n ≤ 3 × 1 0 5 , 1 ≤ a i ≤ 1 0 9 1≤t≤10^4,1≤n≤10^5,1≤\sum n≤3×10^5,1≤a_i≤10^9 1≤t≤104,1≤n≤105,1≤∑n≤3×105,1≤ai≤109。
解题思路
首先可以知道,通过删除操作,任何一个数向前移动而不能向后。
那么如果这个序列中有至少一个 a i a_i ai 满足 ∀ 1 ≤ j ≤ i , a i m o d j = 0 \forall 1 \leq j \leq i,a_i \bmod j=0 ∀1≤j≤i,aimodj=0,那么一定无解。
根据数论知识
如果一个数 x x x 被一个集合 a a a 的数的
Lcm
整除,那么 x x x 整除这个集合内的所有数。
那么循环判断时,可以顺便维护一下 Lcm
。
时间复杂度 O ( t n ) \mathcal O(tn) O(tn)。
反之一定有解。
CODE
#include <bits/stdc++.h>
using namespace std;
long long T, n, a[100005];
long long gcd(long long a, long long b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
signed main()
{
scanf("%lld", &T);
while (T--)
{
scanf("%lld", &n);
for (long long i = 1; i <= n; i++)
scanf("%lld", &a[i]);
long long now = 1, flag = 1;
for (long long i = 1; i <= n; i++)
{
now = now / gcd(now, i + 1) * (i + 1);
if (a[i] % now == 0)
{
printf("NO\n");
flag = 0;
break;
}
}
if (flag)
printf("YES\n");
}
return 0;
}