Codeforces Round#448 C

Posted amitherblogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round#448 C相关的知识,希望对你有一定的参考价值。

题意:n个数,问多少个集合的乘积是完全平方数    (x<70)
题解:
完全平方数的因子一定出现偶数个,那么问题就变成有多少个集合的异或和为0

就转化成用线性基来写

第i位为1就说明分解质因数后第i个质数出现了奇数次,为0即出现偶数次,之后再把它转回十进制的另一个数
这样问题就变成了n个数,有多少个集合满足它们异或为0


设线性基的维数是m,那么从非基的nm个数中取任意和做异或得到的数字,均可以通过线性基表出,故答案为2^(nm)1,减一同样是去掉取空集的方案

 

#include <bits/stdc++.h>
using namespace std;
int n,m,x;
const int p=1e9+7;
struct L_B{
    long long d[61];
    L_B(){memset(d,0,sizeof(d));}
    bool insert(long long val){
        for (int i=60;i>=0;i--)
            if (val&(1LL<<i)){
                if (!d[i]){
                    d[i]=val;
                    break;
                }
                val^=d[i];
            }
        return val>0;
    }
};
vector<int> Pr;
bool isprime(int x){
    for(int i=2;i<x;i++)
        if(x%i==0) return false;
    return true;
}
//第i位为1就说明分解质因数后第i个质数出现了奇数次,为0即出现偶数次,之后再把它转回十进制的另一个数
int getst(int x){ int st=0; for(int i=0;i<Pr.size();i++) while(x%Pr[i]==0){
      st^=(1<<i),x/=Pr[i];
     }
return st; } int main(){ for(int i=2;i<=70;i++)if(isprime(i)) Pr.push_back(i); scanf("%d",&n); L_B B; int cnt=0; long long ans=1; for(int i=0;i<n;i++){ scanf("%d",&x); if(!B.insert(getst(x))) //如果插入不成功
       ans=(ans*2)%p; } printf("%lld ",(ans-1+p)%p); return 0; }

 

以上是关于Codeforces Round#448 C的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 448C Painting Fence:分治

Codeforces Round #437 (Div. 2, based on MemSQL Start[c]UP 3.0 - Round 2) E. Buy Low Sell High(代码片

CF Codeforces Round #256 (Div. 2) D (448D) Multiplication Table

Codeforces Round #448 (Div. 2) B. XK Segments进制思维/排序

Codeforces Round #256 (Div. 2/A)/Codeforces448A_Rewards(水题)

Codeforces Round #448 (Div. 2) B