Codeforces 895C - Square Subsets

题意:

 给了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 }

原文地址:https://www.cnblogs.com/doggod/p/8324510.html

时间: 2024-10-08 18:38:08

Codeforces 895C - Square Subsets的相关文章

Codeforces 895C Square Subsets(状压DP 或 异或线性基)

题目链接  Square Subsets 这是白书原题啊 先考虑状压DP的做法 2到70总共19个质数,所以考虑状态压缩. 因为数据范围是70,那么我们统计出2到70的每个数的个数然后从2考虑到70. 设dp[x][mask]为考虑到x这个数的时候,x这个数和之前的所有数中,选出某些数,他们的乘积分解质因数,所有的指数对2取模之后, 状态为mask的方案数. 然后就可以转移了……这个状压DP花了我好几个小时……真是弱啊 哦对最后还要特判1的情况. 每个1选或不选都可以,然后考虑只选1的情况,累加

Codeforces 432E Square Tiling(构造+贪心)

我们通常这么写 using (SqlDataReader drm = sqlComm.ExecuteReader()) { drm.Read();//以下把数据库中读出的Image流在图片框中显示出来. MemoryStream ms = new MemoryStream((byte[])drm["Logo"]); Image img = Image.FromStream(ms); this.pictureBox1.Image = img; } 我的写数据 private void b

codeforces 432E Square Tiling

codeforces 432E Square Tiling 题意 题解 代码 #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define mp make_pair #define pb push_back #define rep(i, a, b) for(int i=(a); i<(b); i++) #define sz(x) (int)x.size() #define d

codeforces 432E Square Tiling 贪心

题目大意:给定一个n?m的矩阵,要求用正方形砖块覆盖,使得任意两块同颜色的正方形砖块不相邻且字典序最小 枚举每一块砖,如果这个位置为空,就填入字典序最小的砖块,然后将边长一格格拓展 如果当前右侧位置可以填入字典序更小的砖块,就不拓展 否则判断能否拓展并拓展 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 110 using name

CF895C Square Subsets (组合数+状压DP+简单数论)

题目大意:给你一个序列,你可以在序列中任选一个子序列,求子序列每一项的积是一个平方数的方案数. 1<=a[i]<=70 因为任何一个大于2的数都可以表示成几个质数的幂的乘积 所以我们预处理70以内的质数,把它作为二进制状压的状态,每个在序列中出现数Hash一下,组合数推一下 所以把奇次幂的状态表示为1,偶次幂的状态就是0,比如6就是11,42就是1011 而平方数的每个质因子的指数都是偶数,所以最终结果的状态就是0000000... 转移的过程,两个数的乘积,就是这两个数的质因子二进制的状态的

CodeForces 1A Theatre Square

A - Theatre Square Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 1A Description Theatre Square in the capital city of Berland has a rectangular shape with the size n × m meters. On the

Codeforces Round #249 (Div. 2) A. Black Square

水题 #include <iostream> #include <vector> #include <algorithm> using namespace std; int main(){ vector<int> a(4); cin >> a[0] >> a[1]>>a[2]>>a[3]; string str; cin >> str; int res = 0; for(int i = 0 ; i

Codeforces 828B Black Square(简单题)

Codeforces 828B Black Square(简单题) Description Polycarp has a checkered sheet of paper of size n?×?m. Polycarp painted some of cells with black, the others remained white. Inspired by Malevich's "Black Square", Polycarp wants to paint minimum pos

codeforces 711B - Chris and Magic Square

题目链接:http://codeforces.com/problemset/problem/711/B 题目大意: 输入 n ,输入 n*n 的矩阵,有一个占位 0 , 求得将 0 位置换成其他的整数 使得矩阵 行列斜 和全部相等. 代码状态: 一把辛酸泪