Hdu 5833 Zhu and 772002(高斯消元解异或方程组)

来源:互联网 发布:115浏览器for mac 编辑:程序博客网 时间:2024/06/13 22:38

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5833

思路:

将每个数质因数分解,若该位质因数指数为偶数,则该位a[i]为0,否则该位a[i]为1(记a[i]为质因数分解后第i个质数所对应值)。

合法方案为积的各位质因子个数对应值a[i]异或值为0。

例3=3^1,4=2^2,则3*3*4对应:

2           3

0   (1 xor 1=0)

则可列方程组

a11x1+a12x2+...+a1nxn=0

a21x1+a22x2+...+a2nxn=0

...

an1x1+an2x2+...+annxn=0

a[i][j]表示第i个质数在第j个数所对应值(奇数个为1,偶数个为0)。

x[i]表示是否选择数字i,若选择为1,否则为0。

则ans=2^(n-r)-1(r为自由变量个数,减一表示不能全为0)


#include<queue>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#define debuusing namespace std;typedef long long LL;const int maxn=350;const int maxp=350;const int maxx=2000;const int mod=1e9+7;struct Matrix{    int f[maxn][maxn];};Matrix e;int v[maxx];int n,m,q,k;int a[maxn][maxp];vector<int> prime;int Guass(Matrix a,int n,int m){    int i=1,j=1,k,r,u;    while(i<=n&&j<=m)    {        r=i;        for(k=i; k<=n; k++)            if(a.f[k][j])            {                r=k;                break;            }        if(a.f[r][j])        {            if(r!=i)                for(k=0; k<=m+1; k++)                    swap(a.f[r][k],a.f[i][k]);            for(u=i+1; u<=n; u++)                if(a.f[u][j])                    for(k=i; k<=m+1; k++)                        a.f[u][k]^=a.f[i][k];            i++;        }        j++;    }    for(u=i; u<=n; u++)        if(a.f[u][m+1]) return -1;    return i-1;}void prepare(){    for(int i=2; i<maxx; i++)    {        if(!v[i])        {            prime.push_back(i);            for(int j=i*i; j<maxx; j+=i) v[j]=1;        }    }}void change(int id,LL x){    for(int i=0; i<prime.size(); i++)    {        while(x%prime[i]==0)        {            a[id][i+1]++;            x/=prime[i];            a[id][i+1]%=2;        }    }}LL pow_mod(LL a,LL b,LL mod){   LL t=1,y=a;   while(b)   {       if(b&1) t=(t*y)%mod;       y=(y*y)%mod;       b>>=1;   }   return t;}int main(){#ifdef debug    freopen("in.in","r",stdin);#endif // debug    int t,cas=0;    scanf("%d",&t);    prepare();    while(t--)    {        memset(a,0,sizeof(a));        printf("Case #%d:\n",++cas);        scanf("%d",&n);        for(int i=1; i<=n; i++)        {            LL x;            scanf("%I64d",&x);            change(i,x);        }        memset(e.f,0,sizeof(e.f));        for(int i=0; i<prime.size(); i++)            for(int j=1; j<=n; j++)                e.f[i+1][j]=a[j][i+1];        for(int i=0; i<prime.size(); i++) e.f[i+1][n+1]=0;        int r=Guass(e,prime.size(),n);        if(r==-1) printf("0\n");        else printf("%I64d\n",pow_mod(2,n-r,mod)-1);    }    return 0;}


0 0
原创粉丝点击