hdu 5833 || ccpc 2016 网络赛 1002 Zhu and 772002 (高斯消元)
题意:n个数,保证每个数的素因子不超过2000,从中取若干个,问乘积是完全平方数的方案数。
思路: 完全平方数就是要求每个质因子的指数是偶数次。
列方程组,a1,a2,a3……am分别表示bi是否在集合中。对于每一个素因子,建立异或方程组,要求因子个数为偶数,即异或为0
然后得到自由元的个数为num,答案为2^num-1 (减去空集)
1#include <iostream>
2#include <string.h>
3#include <math.h>
4#include <queue>
5#include <algorithm>
6#include <stdlib.h>
7#include <map>
8#include <set>
9#include <stdio.h>
10using namespace std;
11typedef long long LL ;
12#define pi acos(-1.0)
13const int mod=1e9+7;
14const int INF=1e9;
15const double eqs=1e-9;
16const int N=310;
17LL mat[N][N], a[N], equ, var, prime[N];
18LL c[N];
19LL gauss()
20{
21 LL i, j, k, h, max_r, tmp;
22 for(i=0,j=0;i<equ&&j<var;i++,j++){
23 max_r=i;
24 for(k=i+1;k<equ;k++){
25 if(mat[k][j]>mat[max_r][j]) max_r=k;
26 }
27 if(max_r!=i){
28 for(k=j;k<=var;k++){
29 swap(mat[i][k],mat[max_r][k]);
30 }
31 }
32 if(mat[i][j]==0){
33 i--;
34 continue ;
35 }
36 for(k=i+1;k<equ;k++){
37 if(mat[k][j]==0) continue ;
38 for(h=j;h<=var;h++){
39 mat[k][h]^=mat[i][h];
40 }
41 }
42 }
43 tmp=i;
44 //printf("%d\n",tmp);
45 for(;i<equ;i++){
46 if(mat[i][var]){
47 return 0;
48 }
49 }
50 return var-tmp;
51}
52void output(int k)
53{
54 LL i, j, x, y, tmp;
55 memset(c,0,sizeof(c));
56 c[0]=1;
57 x=0;
58 for(i=0;i<k;i++){
59 for(j=0;j<=80;j++){
60 y=(c[j]*2+x);
61 x=(c[j]*2+x)/10;
62 c[j]=y;
63 }
64 }
65 for(i=80;i>=0;i--){
66 if(c[i]){
67 tmp=i;
68 break;
69 }
70 }
71 c[0]--;
72 for(i=tmp;i>=0;i--){
73 printf("%lld",c[i]);
74 }
75 puts("");
76}
77void init()
78{
79 LL i, j, cnt=0, flag;
80 for(i=2;;i++){
81 flag=0;
82 for(j=2;j*j<=i;j++){
83 if(i%j==0){
84 flag=1;
85 break;
86 }
87 }
88 if(!flag){
89 prime[cnt++]=i;
90 }
91 if(cnt==305) return ;
92 }
93}
94LL ksm(LL a,LL b)
95{
96 LL res = 1LL;
97 while (b>0)
98 {
99 if (b&1)
100 res = (res*a)%MOD;
101 b = b/2;
102 a = (a*a)%MOD;
103 }
return res;
}
int main()
{
1 // freopen("code/in.txt","r",stdin);
2 LL t, n, i, j, x, cnt, ans;
3 int T;
4 cin>>T;
5 int cas = 0 ;
6 while (T--){
7 printf("Case #%d:\n",++cas);
8 init();
9 scanf("%lld",&n);
10 t = 305;
11 for(i=0; i<n; i++) {
12 scanf("%lld",&a[i]);
13 }
14 for(i=0; i<n; i++) {
15 x=a[i];
16 for(j=0;j<t;j++){
17 cnt=0;
18 while(x%prime[j]==0){
19 cnt++;
20 x/=prime[j];
21 }
22 mat[j][i]=(cnt&1);
23 }
24 }
25 for(i=0;i<t;i++){
26 mat[i][n]=0;
27 }
28 equ=t;
29 var=n;
30 ans=gauss();
31 if(ans)
32 printf("%lld\n",ksm(2,ans)-1);
33 else puts("0");
34 }
35 return 0;
36}