• Codeforces 895C


    题意:

     给了n个数,要求有几个子集使子集中元素的和为一个数的平方。

    题解:

     因为每个数都可以分解为质数的乘积,所有的数都小于70,所以在小于70的数中一共只有19个质数。可以使用状压DP,每一位上0表示这个质数的个数为偶数个,1表示为奇数个。这样的话,如果某个数为一个数的平方的话,那么每个质数个数都是偶数,用0可以表示。从1-70开始状压DP,先存下每个数出现多少次,然后dp转移,dp转移时分别计算某个数出现奇数次还是偶数次的方案数.

    这里有一个公式:C(n,0)+C(n,2)+……=C(n,1)+C(n,3)+……=2^(n-1);
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAX_N = 1e5+7;
     4 const int MOD = 1e9+7;
     5 int vec[75],tran[75],sum[MAX_N];
     6 int dp[75][(1<<19)+4];
     7 int prime[20] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 };
     8 int main()
     9 {
    10     int N,M,T;
    11     while(cin>>N)
    12     {
    13         memset(vec,0,sizeof(vec));
    14         memset(tran,0,sizeof(tran));
    15         memset(sum,0,sizeof(sum));
    16         memset(dp,0,sizeof(dp));
    17         for(int i=0;i<N;i++)
    18         {
    19             int temp;
    20             scanf("%d",&temp);
    21             vec[temp] ++;
    22         }
    23         for(int i=1;i<=70;i++)
    24         {
    25             int t = i;
    26             for(int j=0;j<19;j++)
    27             {
    28                 while(t%prime[j] == 0)
    29                 {
    30                     tran[i] ^= (1<<j);
    31                     t /= prime[j];
    32                 }
    33             }
    34         }
    35         sum[0] = 1;
    36         for(int i=1;i<=N;i++)
    37         {
    38             sum[i] = (sum[i-1]*2)%MOD;
    39         }
    40         dp[0][0] = 1;
    41         for(int i=1;i<=70;i++)
    42         {
    43 
    44             if(vec[i] == 0)
    45             {
    46                 for(int j=0;j<(1<<19);j++) dp[i][j] = dp[i-1][j];
    47             }
    48             else
    49             {
    50                 for(int j=0;j<(1<<19);j++)
    51                 {
    52                     //奇数
    53                     dp[i][j^tran[i]] = (dp[i][j^tran[i]] + (long long )dp[i-1][j]*sum[vec[i]-1])%MOD;
    54                     //偶数
    55                     dp[i][j] = (dp[i][j] + (long long )dp[i-1][j]*sum[vec[i]-1])%MOD;
    56                 }
    57             }
    58         }
    59         cout<<(dp[70][0] - 1)%MOD<<endl;
    60     }
    61     return 0;
    62 }
  • 相关阅读:
    Java
    Java
    Java
    Java
    NYOJ 127 星际之门(一)
    BNUOJ 1013 YC大牛的判题任务
    BNUOJ 1011 人工智能?
    HDU 1035 Robot Motion
    HDU 1214 圆桌会议
    NYOJ 86 找球号(一)
  • 原文地址:https://www.cnblogs.com/doggod/p/8324510.html
Copyright © 2020-2023  润新知