SGU 200 Cracking RSA (高斯消元)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=200

题意:给定m个数,这些数的质因数都是前n个素数。求m有多少个不空子集使得子集中的数字之积为完全平方数。

思路:建立矩阵n*m。a[i][j]表示第j个数中含有第i个素数的个数。解的个数为m-非全零行的个数P的2^P。我的理解是这样,比如两个方程5个未知数:

x1+x2+x3+x4+x5=0;

x3+x5=0;

那么答案是2^(5-2)=8。我们从上向下消元。我们发现,决定第一个方程的变元是x1,决定第二个的是x3。那么对于第二个方程,只要x5确定,x3就确定,对于x5有两种情况;然后对于第一个式子x3和x5已经确定,那么x2和x4是变元,只要x2和x4确定,x1就确定。这里有4种情况,一共有2*4=8。那么其实答案最后就是看有多少个变元。此外此题还要用到高精度。

int n,m;

int a[105][105],b[105];

int pr[105];







int Gauss()

{

    int i,k,t,M=m,p;

    for(i=1;i<=n;i++)

    {

        for(p=1;p<=m;p++) if(a[i][p]) break;

        if(p>m) continue;

        for(k=i+1;k<=n;k++) if(a[k][p])

        {

            for(t=1;t<=m;t++)

            {

                a[k][t]^=a[i][t];

            }

        }

        M--;

    }

    return M;

}





BigNum B;



int ok(int x)

{

    if(x==2||x==3) return 1;

    for(int i=2;i*i<=x;i++) if(x%i==0) return 0;

    return 1;

}



int main()

{

    RD(n,m);

    int Num=0,i,k;

    for(i=2;Num<n;i++) if(ok(i)) pr[++Num]=i;

    FOR1(i,m) RD(b[i]);

    for(i=1;i<=m;i++)

    {

        for(k=1;k<=n&&pr[k]<=b[i];k++) if(b[i]%pr[k]==0)

        {

            while(b[i]%pr[k]==0)

            {

                a[k][i]^=1;;

                b[i]/=pr[k];

            }

        }

    }

    B=BigNum(2).power(Gauss())-BigNum(1);

    B.print();

    puts("");

    return 0;

}

  

你可能感兴趣的:(rack)