[关闭]
@Chilling 2017-07-08T20:34:53.000000Z 字数 2179 阅读 825

HDU-5833: Zhu and 772002

高斯消元


Problem Description

Zhu and 772002 are both good at math. One day, Zhu wants to test the ability of 772002, so he asks 772002 to solve a math problem.

But 772002 has a appointment with his girl friend. So 772002 gives this problem to you.

There are n numbers a1,a2,...,an. The value of the prime factors of each number does not exceed 2000, you can choose at least one number and multiply them, then you can get a number b.

How many different ways of choices can make b is a perfect square number. The answer maybe too large, so you should output the answer modulo by 1000000007.

Input

First line is a positive integer T , represents there are T test cases.

For each test case:

First line includes a number ,next line there are n numbers a1,a2,...,an,.

Output

For the i-th test case , first output Case #i: in a single line.

Then output the answer of i-th test case modulo by 1000000007.

Sample Input

2
3
3 3 4
3
2 2 2

Sample Output

Case #1:
3
Case #2:
3

题意: t组样例,每组样例输入一个n,表示有n个数ai,要从这n个数中随便选几个出来,让他们的乘积成为一个完全平方数,问有多少种方案。方案数模1e9+7。

分析:首先,对于一个完全平方数来说,它的每个相同素因子,一定有偶数个,比如36,素因子2,2,3,3,2和3都是两个。那么我们将每一个输入的x进行素因子分解。一个列数为n的矩阵,行表示素数,从上到下分别为素数2,3,5,7……出现的次数。如果某个素因子出现奇数次,那么记为1,否则为0。如第一个数素因子分解之后,素因子3出现奇数次,其他都为偶数次,那么mp[1][0]=1,其他mp[i][0]为0。
由于完全平方数相同素因子为偶数个,也就是说,将这个矩阵进行高斯消元之后,增广矩阵最后一列为全0。我们求出自由元的个数fre,那么是否就为最终的答案?不……还要刨去所有数都不选的情况,因此得到……


  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. const int maxn=350;
  5. const int mod=1e9+7;
  6. int prime[350],cnt;
  7. int mp[350][350];
  8. void getPrime()
  9. {
  10. prime[cnt++]=2;
  11. for(int i=3;i<=2000;i+=2)
  12. {
  13. int flag=1;
  14. for(int j=2;j*j<=i;j++)
  15. {
  16. if(i%j==0)
  17. {
  18. flag=0;
  19. break;
  20. }
  21. }
  22. if(flag) prime[cnt++]=i;
  23. }
  24. }
  25. int resolution(int col,LL x)
  26. {
  27. int m=0;
  28. for(int i=0;i<cnt;i++)
  29. {
  30. while(x%prime[i]==0)
  31. {
  32. mp[i][col]^=1;
  33. x/=prime[i];
  34. m=max(m,i+1);
  35. }
  36. }
  37. return m;
  38. }
  39. int gauss(int A[][maxn],int n,int m)
  40. {
  41. int res=0,r=0;
  42. for(int i=0;i<m&&r<m;i++)
  43. {
  44. for(int j=r;j<n;j++)
  45. {
  46. if(A[j][i]==1)
  47. {
  48. for(int k=i;k<=m;k++)
  49. swap(A[j][k],A[r][k]);
  50. break;
  51. }
  52. }
  53. if(A[r][i]==0)
  54. {
  55. res++;
  56. continue;
  57. }
  58. for(int j=0;j<n;j++)
  59. {
  60. if(A[j][i]==1&&j!=r)
  61. {
  62. for(int k=i;k<=m;k++)
  63. A[j][k]^=A[r][k];
  64. }
  65. }
  66. r++;
  67. }
  68. return res;
  69. }
  70. int main()
  71. {
  72. int t,o=0;
  73. getPrime();
  74. scanf("%d",&t);
  75. while(t--)
  76. {
  77. memset(mp,0,sizeof(mp));
  78. LL x;
  79. int n,y=0,fre=0;
  80. scanf("%d",&n);
  81. for(int i=0;i<n;i++)
  82. {
  83. scanf("%lld",&x);
  84. y=max(y,resolution(i,x));
  85. }
  86. fre+=gauss(mp,y,n);
  87. LL ans=1;
  88. for(int i=1;i<=fre;i++)
  89. ans=ans*2%mod;
  90. ans--;
  91. printf("Case #%d:\n%lld\n",++o,ans);
  92. }
  93. return 0;
  94. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注