高斯消元+大数SGU200

来源:互联网 发布:行业研究数据来源 编辑:程序博客网 时间:2024/06/17 03:11

Cracking RSA
Time Limit:250MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u

SubmitStatus

Description

200. Cracking RSA

time limit per test: 0.25 sec.
memory limit per test: 65536 KB
input: standard
output: standard



The following problem is somehow related to the final stage of many famous integer factorization algorithms involved in some cryptoanalytical problems, for example cracking well-known RSA public key system.

The most powerful of such algorithms, so called quadratic sieve descendant algorithms, utilize the fact that if n = pq where p and q are large unknown primes needed to be found out, then if v2=w 2 (mod n), u ≠ v (mod n) and u ≠ -v (mod n), then gcd(v + w, n) is a factor of n (either p or q).

Not getting further in the details of these algorithms, let us consider our problem. Given m integer numbers b1, b 2, ..., b m such that all their prime factors are from the set of first t primes, the task is to find such a subset S of {1, 2, ..., m} that product of bi for i from S is a perfect square i.e. equal to u 2 for some integer u. Given such S we get one pair for testing (product of S elements stands for v when w is known from other steps of algorithms which are of no interest to us, testing performed is checking whether pair is nontrivial, i.e. u ≠ v (mod n) and u ≠ -v (mod n)). Since we want to factor n with maximum possible probability, we would like to get as many such sets as possible. So the interesting problem could be to calculate the number of all such sets. This is exactly your task.

Input

The first line of the input file contains two integers t and m (1 ≤ t ≤ 100, 1 ≤ m ≤ 100). The second line of the input file contains m integer numbers bi such that all their prime factors are from t first primes (for example, if t = 3 all their prime factors are from the set {2, 3, 5}). 1 ≤ bi ≤ 10 9 for all i.

Output

Output the number of non-empty subsets of the given set {b i}, the product of numbers from which is a perfect square


Sample test(s)

Input

3 4
9 20 500 3

Output

3
[submit]
[forum]

Author:Andrew StankevichResource:Petrozavodsk Winter Trainings 2003Date:2003-02-06






题意:给出m个数,他们的质因子包含在前t个质数中, 问存在多少个子集,自己中的数的乘积为平方数

思路:只需要每个质因子出现偶数次,高斯消元,对于前t个素数,每个列一个方程,出现偶数次相当于本身就是偶数次的可以随便取,奇数次的异或值为0

则可以通过高斯消元解异或方程组来解决

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=110;const int maxm=10001;int A[maxn],a[maxn][maxn];int prime[10010];bool vis[10010];int T,M,num,N;int equ,var,x[maxn];bool free_x[maxn];void get_prime(){    num=0;    memset(vis,0,sizeof(vis));    for(int i=2;i<maxm;i++)    {        if(!vis[i])            prime[num++]=i;        for(int j=0;j<=num;j++)        {            if(prime[j]*i>maxm)break;            vis[i*prime[j]]=1;            if(i%prime[j]==0)break;        }    }}int Gauss(){    memset(x,0,sizeof(x));    memset(free_x,0,sizeof(free_x));    int row=0,col=0;    int free_num=0;    for(;row<equ&&col<var;row++,col++)    {        int r=row;        for(int i=row+1;i<equ;i++)            if(abs(a[i][col])>abs(a[r][col]))r=i;        if(row!=r)            for(int i=col;i<=var;i++)swap(a[r][i],a[row][i]);        if(!a[row][col])        {            row--;            free_x[free_num++]=col;            continue;        }        for(int i=row+1;i<equ;i++)        {            if(a[i][col])            {                for(int j=col;j<=var;j++)                    a[i][j]^=a[row][j];            }        }    }    for(int i=row;i<equ;i++)        if(a[i][var])return -1;    if(var>row)return var-row;    for(int i=var-1;i>=0;i--)    {        x[i]=a[i][var];        for(int j=i+1;j<var;j++)            x[i]^=(a[i][j]&&x[j]);    }    return 0;}int ans[maxn];void cal(){    for(int i=1;i<=ans[0];i++)        ans[i]*=2;    int c=0;        for(int i=1;i<=ans[0];i++)    {        if(ans[i]>=10)        {            ans[i]%=10;            ans[i+1]++;        }    }    if(ans[ans[0]+1]>0)ans[0]++;}void sub(){    ans[1]--;    int i=0;    while(ans[i]<0)    {        ans[i]+=10;        ans[++i]--;    }    if(ans[ans[0]]==0)ans[0]--;    }void print(){    for(int i=ans[0];i>=1;i--)        printf("%d",ans[i]);    if(!ans[0])printf("0\n");    printf("\n");}int main(){    get_prime();    while(scanf("%d%d",&T,&N)!=EOF)    {        for(int i=1;i<=N;i++)scanf("%d",&A[i]);        memset(a,0,sizeof(a));        for(int i=1;i<=N;i++)        {            int x=A[i];            for(int j=0;j<T;j++)            {                int cnt=0;                while(x%prime[j]==0){cnt++,x/=prime[j];}                a[j][i-1]=(cnt&1);            }        }        equ=T,var=N;        int cnt=Gauss();        memset(ans,0,sizeof(ans));        ans[0]=ans[1]=1;        for(int i=0;i<cnt;i++)            cal();        sub();        print();    }    return 0;}



0 0
原创粉丝点击