HDU 5833 Zhu and 772002

来源:互联网 发布:sop8单片机实践应用 编辑:程序博客网 时间:2024/05/16 18:34

高斯消元解异或方程。
题意:

给你n个数,然后让你选择一些数,乘起来成为完全平方数,问你有多少种方案。
分析:

例如四个整数4,6,10,15。他们的素因子只有2,3,5这3种,把他们写成01向量的形式4 = 2^2  * 3^0 * 5 ^ 0  ->(2,0,0);
6 = 2^1 * 3^1 * 5 ^0 ->(1,1,0), 10 = 2^1 * 3^0 * 5^1 ->(1,0,1), 15 = 2^0 * 3^1 * 5^1 ->(0,1,1).
选出来的数乘积为2^(2*x1 + x2 + x3) * 3^(x2 + x4) * 5^(x3 + x4); 要使这个数为平方数,每个幂都为偶数,
即             
    x2+x3 = 0(mod2)
    x2+x4 = 0(mod2)
    x3+x4 = 0(mod2)
或   
   x2 xor x3 = 0
   x2 xor x4 = 0
   x3 xor x4 = 0
就变成了一个求线性方程组的秩, 最后减一, 因为题意不允许一个都不选,即0 0 0 0这组不成立。
代码:
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#define MAX 2000 + 10#define MOD 1000000007using namespace std;long long c[MAX][505], p[MAX], v[MAX], a[MAX], cnt, n;//c矩阵,p素数表,cnt素数的个数void mprime()//打素数表{    int i,j;    memset(v,0,sizeof(v));    memset(p,0,sizeof(p));    cnt=0;    for(i=2; i<=2000; i++)    {        if(!v[i])        {            p[++cnt]=i;            for(j=i; j<=2000; j+=i)            {                v[j]=1;            }        }    }}int Rank()//计算秩{    int i,j,k,r,u;    i=0;    j=0;    while(i<=cnt && j<=n)    {        r=i;        while(!c[r][j] && r<=cnt)            r++;        if(c[r][j])        {            swap(c[i],c[r]);//如果发现了第r行第j列为1,就讲r行和i行行互换(初等行变换)            for(u=i+1; u<=cnt; u++)            {                if(c[u][j])                {                    for(k=i; k<=n; k++)                    {                        c[u][k]=c[u][k]^c[i][k];//每找到一个未知数就对其进行亦或处理,去掉系数c[i][k]                    }                }            }            i++;        }        j++;    }    return i;}int main(){    mprime();    int cns = 1, T;    scanf("%d", &T);    while(T--)    {        scanf("%lld", &n);        memset(c, 0, sizeof(c));        for(int i = 1; i <= n; i++)        {            scanf("%lld", &a[i]);        }        for(int i = 1; i <= n; i++)        {            for(int j = 1; j <= cnt; j++)            {                long long num = a[i];                if(num%p[j] == 0)                {                    while(num%p[j] == 0)                    {                        num /= p[j];                        c[j][i] = c[j][i]^1;                    }                }            }        }        long long k = (n-Rank());        long long ans = 1;        for(int i = 1; i <= k; i++)            ans = (ans*2) % MOD;        printf("Case #%d:\n", cns++);        printf("%lld\n", ans-1);    }    return 0;}



原创粉丝点击