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); } } }