https://codeforces.com/contest/1470/problem/B

 

看到lcm和gcd第一反应分解质因子(不然求啥

发现若x,y有关联,那么设X=p1(a1)p2(a2)...pn(an),同理Y=p1(b1)p2(b2)...pn(bn);

则对某一个pi,ai-bi应该为偶数;

也就是相同素数因子上的值应该同奇同偶。

且若a和b相关,b和c相关,那么a和c也相关,所以序列可以看成若干个组。

本来设想:

对每一个读取进来的数,分解完后与当前有的若干个组check,若符合条件则加入,不符合则自建一个。

这里的符合条件就是同奇同偶了。

打个并查集+check啥的。

问题是我使用按位比较过去检查是否符合条件,不知道常数会有多大。

标解对此给出的解法是把能消去的最大平方因数消去,然后用hash存010000111啥的。

这样做的好处就是比较直接降到了O(1)。

哈希我用得很少,这题可以练习哈希,消最大平方数的原理就是其实也不用关注到底具体数多少啦,只要知道奇偶性就好了,那么0,1其实就够了。

这就很nice。

到这里解决了第一个问题,盲目check费时。

第二个问题:怎么对付查询?

我想查询的次数是有限的,因为若组内的元素个数为偶数的话,那么只要经过一次相乘,所有因数的次数都会变成偶数,那么对于所有元素个数为偶数的来说,

大家突然就是一家人了,笑。

那么如果是奇数的话,偶数不会受到干扰,奇数仍然是奇数。

假设经过了第一轮变形,组合的总数肯定变少了,同理越往下变越少,那么肯定是有尽头的。

所以w很大我们也不怕。

题解一句只考虑w=1和w=0(这跟我的总数变少的感觉是符合的)让我一下子想到了奇偶性。。。

那就是对两个元素个数为奇数的组,再怎么相乘也不会在一起。

因为相乘对他们其实并没有影响,而他们本来就不在一起。

经过一次变形后,所有偶数组合并,所有奇数组不变。

总结:

这道题想了个开头,在题解帮助下被提示了消去x²这个点,以及w=1,然后想了个结尾。

算是第一次多少还算有想法的数论+思维题,小小纪念一下很弱的自己。

 

#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int>Hash;
int t,q,n;
void solve(int x)
{
	for(int i=2;;i++)
	{
		int square=i*i;
		if(x<square)
		{
			break;
		}
		while(x%square==0&&x>=square)
		{
			x/=square;
		}
	} 
/*	for(int i = 2; ; ++ i) {
        int even = i * i;
        while(x % even == 0 && x >= even) x /= even;
        if(x < even) break;
    }*/
	Hash[x]++;
}
int main( )
{
	
	
	//freopen("9171.in","r",stdin);
	
	scanf("%d",&t);
	while(t--)
	{   Hash.clear();
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			int x;
			scanf("%d",&x);
			solve(x);
		}
		
		int ans1=-1,ans2=0;
		
		
		for(auto it=Hash.begin();it!=Hash.end();++it)
		{
			ans1=max(ans1,it->second);
			
			if(it->first==1||it->second%2==0)
			{
			  ans2+=it->second;	
			}
		}
		
	    ans2=max(ans2,ans1);
		
		scanf("%d",&q);
		
		
		for(int i=1;i<=q;i++)
		{
			long long w;
			scanf("%lld",&w);

			if(w==0)
			{
				printf("%d\n",ans1);
			}
			else printf("%d\n",ans2);
		}
	}
}