B. Strange Definition(Codeforces Round #694 (Div. 1)题解)
题目链接:B. Strange Definition
思路:因为\(gcd(x,y) = p_1^{min}*p_2^{min}*...*p_n^{min}\),\(lcm(x,y) = p_1^{max}*p_2^{max}*...*p_n^{max}\),所以任意两个点间若能相关,则必有\(\frac{lcm(x,y)}{gcd(x,y)} = p_1^{max-min}*p_2^{max-min}*...*p_n^{max-min}\)其中\(max-min\)一定为偶数,即\(x,y\)每一个素因子的个数的奇偶性相同,然后我们发现在经过一秒之后会变成什么样,以一个节点x为例,设与x相关的集合为\(a_1,a_2,...,a_n\),分类讨论:
1.因为和x相关的一定是对于x每一个素因子个数奇偶性均相同的,所以如果x的一个素因子个数为偶数,那么在经过一秒之后x对于该素因子变为\(p^{\sum_1^n{cnt(a_i)}}\)所以在经过一秒后,与变化前奇偶性相同。
2.如果x的一个素因子个数为奇数,
(1)如果与x相关的集合数目为偶数,那么\(p^{\sum_1^n{cnt(a_i)}}\)的指数位置\(\sum_1^n{cnt(a_i)}\)一定为偶数,所以经过一秒之后变为偶数,返回到第一种状态。
(2)如果与x相关的集合数目为奇数,那么\(p^{\sum_1^n{cnt(a_i)}}\)的指数位置\(\sum_1^n{cnt(a_i)}\)一定为奇数,所以无论经过几秒,都是奇数。
所以我们可以根据每一个素因子的奇偶性,将数组分到一些集合中去,方法主要为通过Hash的方式分配集合,然后记录集合最大值,然后对于每一次询问,第0秒是一个答案,非第0秒是一个答案(因为在第1秒有奇->偶的情况)。复杂度\(\Theta(nlog(n))\)
\(Code:\)
#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#define ch() getchar()
#define pc(x) putchar(x)
#include<stack>
#include<unordered_map>
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define lowbit(x) x&(-x)
#define ll long long
#define ull unsigned long long
#define pb emplace_back
#define mp make_pair
#define PI acos(-1)
using namespace std;
template<typename T>void read(T&x){
static char c;
static int f;
for(c=ch(),f=1; c<'0'||c>'9'; c=ch())if(c=='-')f=-f;
for(x=0; c>='0'&&c<='9'; c=ch())x=x*10+(c&15);
x*=f;
}
template<typename T>void write(T x){
static char q[65];
int cnt=0;
if(x<0)pc('-'),x=-x;
q[++cnt]=x%10,x/=10;
while(x)
q[++cnt]=x%10,x/=10;
while(cnt)pc(q[cnt--]+'0');
}
const int N = 1e6+10,M = 3e5+55,inf = 1e6;
const ull P = 1e9+7;
int _,n;
bool st[N];
int prime[N],tot;
void getprime(){
rep(i,2,inf){
if(st[i] == false){
prime[++tot] = i;
if(i>10000)continue;
for(int j=i*i;j<=inf;j+=i)st[j] = true;
}
}
}
unordered_map<ull,vector<int> >S;
int a[M],q;
int mx = -1;
ull ids = -1;
ull arr[M];int tt;
void work(int x,int idx){
int id = 1;
ull sum = 0;
while(prime[id] * prime[id] <= x){
int cnt = 0;
while(x%prime[id] == 0)x/=prime[id],cnt++;
if(cnt%2)sum = sum*P + prime[id];
id++;
}
if(x!=1)sum = sum * P + x;
S[sum].pb(idx);
if((int)S[sum].size()>mx){
ids = sum;
mx = (int)S[sum].size();
}
if((int)S[sum].size() == 1 and sum != 0)arr[++tt] = sum;
}
void solve(){
getprime();
read(_);
while(_--){
tt = 0;mx = -1;ids = -1;
S.clear();
read(n);
rep(i,1,n){
read(a[i]);
work(a[i],i);
}
int nxt = (int)S[0].size();
rep(i,1,tt){
if((int)S[arr[i]].size()%2==0)nxt+=(int)S[arr[i]].size();
}
nxt = max(mx,nxt);
read(q);
while(q--){
ll k;
read(k);
if(k)write(nxt);
else write(mx);
pc('\n');
}
}
}
signed main(){solve();return 0; }