来点gcd
题意:
给定一个含有
n
n
n 个数的序列,
m
m
m 次询问,每次查询给出一个整数
x
x
x,问是否能在序列中选出一些数,满足这些数的
g
c
d
=
x
gcd=x
gcd=x,如果只选出一个数,那么
g
c
d
gcd
gcd 就等于这个数。
思路:
首先要使选出的数的
g
c
d
=
x
gcd=x
gcd=x,那么这些数一定都是
x
x
x 的倍数。考虑到
n
<
=
2000
n<=2000
n<=2000,可以预处理所有答案,对于要查询的答案
i
i
i,枚举
i
i
i 的倍数,如果这个倍数出现过就进行
g
c
d
gcd
gcd,扫完一遍判断
g
c
d
gcd
gcd 是否为
i
i
i,如果不为
i
i
i,那么无论怎么选也不会选出
g
c
d
=
i
gcd=i
gcd=i 的序列。
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
using namespace std;
const int maxn = 1e6 + 9;
const int mod = 1e9 + 7;
ll n, m;
bool v[maxn], ans[maxn];
void work()
{
scanf("%lld %lld", &n, &m);
for(int i = 1; i <= n; ++i) v[i] = ans[i] = 0;
for(int i = 1; i <= n; ++i){
int x;scanf("%d", &x);v[x] = 1;
}
for(int i = 1; i <= n; ++i){
ll x = 0;
for(ll j = i; j <= n; j += i) if(v[j])
x = __gcd(x, j);
if(x == i) ans[i] = 1;
}
while(m--)
{
int x;scanf("%d", &x);
if(ans[x]) printf("YES\n");
else printf("NO\n");
}
}
int main()
{
// ios::sync_with_stdio(0);
int TT;cin>>TT;while(TT--)
work();
return 0;
}