SGU 200 Cracking RSA (高斯消元)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题意:给出m个整理,因子全部为前t个素数。问有多少个子集,乘积是平方数
http://acm.sgu.ru/problem.php?contest=0&problem=200
做法:列方程组,a1,a2,a3……am分别表示bi是否在集合中。对于每一个素因子,建立异或方程组,要求因子个数为偶数,即异或为0。
子集个数便是解的个数,高斯消元后求出变元个数num,结果是2^ num-1。除去空集。。
还要模拟一下高精度
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <vector> #include <set> #include <map> #include <queue> #define pb(a) push_back(a) #define mp(a,b) make_pair(a,b) using namespace std; const int N = 100; int t,m; int b[N]; int a[N][N+1]={0}; int prime[N],flag[N*11]={0},cnt=0; void Init(){ for(int i=2;i<=1000;i++){ if(flag[i]) continue; prime[cnt++]=i; if(cnt==t) return ; for(int j=2;j*i<=1000;j++) flag[i*j]=1; } } int gauss(int n,int m){ int i,j; for(i=0,j=0;i<n&&j<m;j++){ int k; for(k=i;k<n;k++) if(a[k][j]) break; if(k<n){ for(int r=j;r<=m;r++) swap(a[i][r],a[k][r]); for(int r=0;r<n;r++){ if(r!=i&&a[r][j]){ for(int t=j;t<=m;t++) a[r][t]^=a[i][t]; } } i++; } } return m-i; } int ans[N]; void out(){ for(int i=ans[0];i>=1;i--) printf("%d",ans[i]); if(ans[0]==0) printf("0"); printf("\n"); } void gao(){ for(int i=1;i<=ans[0];i++){ ans[i]*=2; } for(int p=1;p<=ans[0];p++){ if(ans[p]>=10){ ans[p]%=10; ans[p+1]++; } } if(ans[ans[0]+1]>0) ans[0]++; } void fuck(){ ans[1]--; int p=1; while(ans[p]<0){ ans[p]+=10; ans[++p]--; } if(ans[ans[0]]==0) ans[0]--; } int main(){ scanf("%d%d",&t,&m); Init(); for(int i=0;i<m;i++){ scanf("%d",&b[i]); for(int j=0;j<t;j++){ while(b[i]%prime[j]==0){ a[j][i]^=1; b[i]/=prime[j]; } } } int p=gauss(t,m); ans[0]=ans[1]=1; for(int i=1;i<=p;i++) gao(); fuck(); out(); return 0; }