Codeforces 895.C Square Subsets
4 seconds
256 megabytes
standard input
standard output
Petya was late for the lesson too. The teacher gave him an additional task. For some array a Petya should find the number of different ways to select non-empty subset of elements from it in such a way that their product is equal to a square of some integer.
Two ways are considered different if sets of indexes of elements chosen by these ways are different.
Since the answer can be very large, you should find the answer modulo 109 + 7.
First line contains one integer n (1 ≤ n ≤ 105) — the number of elements in the array.
Second line contains n integers ai (1 ≤ ai ≤ 70) — the elements of the array.
Print one integer — the number of different ways to choose some elements so that their product is a square of a certain integer modulo 109 + 7.
4
1 1 1 1
15
4
2 2 2 2
7
5
1 2 4 5 8
7
In first sample product of elements chosen by any way is 1 and 1 = 12. So the answer is 2^4 - 1 = 15.
In second sample there are six different ways to choose elements so that their product is 4, and only one way so that their product is 16. So the answer is 6 + 1 = 7.
大致题意:选若干个数使得乘积为完全平方数,问方案数.
分析:对于完全平方数,它的每个质因子的次数都是偶数.这道题中ai ≤ 70,质因子最多只有19个,可以考虑状压,记一个状态sta,第i位表示第i个质因子的次数为偶数还是奇数,状态的变化可以通过位运算中的异或运算来解决.那么可以设计状态f[i][j]表示前i个数字中状态为j的方案数,每个数字有选或不选两种选择,转移也比较明确.比较遗憾的是n比较大,2^19 * n不足以通过此题.需要换一种状态的表达方式.
首先状态j,也就是第二维是不能去掉的,关键是第一维该换成什么.2^19已经比较大了,那么第一维也不能很大,能想到的就是表示成1到大小为i的数字中,状态为j的方案数:f[i][j],这样的话不一位一位地去考虑,而是去考虑每个数字出现的次数.转移的时候枚举i和上一次的状态j,那么j能够转移到状态j ^ sta[i]和j,转移到j ^ sta[i]就需要取奇数个i,方案数就是C(n,1) + C(n,3) + ...... = 2^(n-1).j转移到j取偶数个就行了,方案数还是2^(n-1).
最后的答案就是f[70][0].
一道非常好的题.设计状态保留必须的,替换其它的,从题目的要求和信息中找到可以替换的状态.也可以从另一个思路来理解这个替换:不需要知道i在哪几位被选,只需要知道i被选了多少次,记录出现的次数并利用组合数学的知识就可以解决了.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll; const int mod = 1e9 + ; ll n, a[], cnt[], jie[];
int prime[] = { , , , , , , , , , , , , , , , , , , };
int f[][( << ) + ], stu[]; int main()
{
cin >> n;
for (int i = ; i <= n; i++)
{
cin >> a[i];
cnt[a[i]]++;
}
jie[] = ;
for (int i = ; i <= n; i++)
jie[i] = (jie[i - ] * ) % mod;
for (int i = ; i <= ; i++)
{
for (int j = ; j < ; j++)
{
int x = i;
while (x % prime[j] == )
{
stu[i] ^= ( << j);
x /= prime[j];
}
}
}
f[][] = ;
for (int i = ; i <= ; i++)
{
for (int j = ; j < ( << ); j++)
{
if (!cnt[i])
f[i][j] = f[i - ][j];
else
{
f[i][j] = (f[i][j] + jie[cnt[i] - ] * f[i - ][j] % mod) % mod;
f[i][j ^ stu[i]] = (f[i][j ^ stu[i]] + jie[cnt[i] - ] * f[i - ][j] % mod) % mod;
}
}
}
f[][]--;
if (f[][] < )
f[][] += mod;
cout << f[][] << endl; return ;
}
Codeforces 895.C Square Subsets的更多相关文章
- Codeforces Round #448 C. Square Subsets
题目链接 Codeforces Round #448 C. Square Subsets 题解 质因数 *质因数 = 平方数,问题转化成求异或方程组解的个数 求出答案就是\(2^{自由元-1}\) , ...
- Codeforces 895C - Square Subsets
895C - Square Subsets 思路:状压dp. 每个数最大到70,1到70有19个质数,给这19个质数标号,与状态中的每一位对应. 状压:一个数含有这个质因子奇数个,那么他状态的这一位是 ...
- Codeforces 895C Square Subsets(状压DP 或 异或线性基)
题目链接 Square Subsets 这是白书原题啊 先考虑状压DP的做法 $2$到$70$总共$19$个质数,所以考虑状态压缩. 因为数据范围是$70$,那么我们统计出$2$到$70$的每个数的 ...
- Codeforces 828B Black Square(简单题)
Codeforces 828B Black Square(简单题) Description Polycarp has a checkered sheet of paper of size n × m. ...
- CF895C: Square Subsets && 【BZOJ2844】albus就是要第一个出场
CF895C: Square Subsets && [BZOJ2844]albus就是要第一个出场 这两道题很类似,都是线性基的计数问题,解题的核心思想也一样. CF895C Squa ...
- Codeforces 895C Square Subsets:状压dp【组合数结论】
题目链接:http://codeforces.com/problemset/problem/895/C 题意: 给你n个数a[i].(n <= 10^5, 1 <= a[i] <= ...
- Codeforces 895C - Square Subsets 状压DP
题意: 给了n个数,要求有几个子集使子集中元素的和为一个数的平方. 题解: 因为每个数都可以分解为质数的乘积,所有的数都小于70,所以在小于70的数中一共只有19个质数.可以使用状压DP,每一位上0表 ...
- Codeforces Round #448 (Div. 2)C. Square Subsets
可以用状压dp,也可以用线型基,但是状压dp没看台懂... 线型基的重要性质 性质一:最高位1的位置互不相同 性质二:任意一个可以用这些向量组合出的向量x,组合方式唯一 性质三:线性基的任意一个子集异 ...
- CodeForces 1A Theatre Square
A - Theatre Square Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u ...
随机推荐
- 【bzm-Random CSV Data Set Config】 -jmeter - 文件中随机取参的方法,(插件自带)
文件中随机取参数的方法 Random CSV Data Set Config
- 【转】PHPCMS v9 自定义表单添加验证码验证
1. 在 \phpcms\templates\default\formguide\show.html 中添加验证码显示 <input type="text" id=&quo ...
- mysql查看锁表与解锁
查看锁表语句 show OPEN TABLES where In_use > 0; 找到锁表的进程 show processlist; 删除锁表进程 kill 51045123;
- Centos7 Zabbix添加主机、图形、触发器
制作自定义key zabbix自带模板Template OS Linux (Template App Zabbix Agent)提供CPU.内存.磁盘.网卡等常规监控,只要新加主机关联此模板,就可自动 ...
- 关于XML文档操作类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.X ...
- underscore.js源码解析(三)
最近工作比较忙,做不到每周两篇了,周末赶着写吧,上篇我针对一些方法进行了分析,今天继续. 没看过前两篇的可以猛戳这里: underscore.js源码解析(一) underscore.js源码解析(二 ...
- Mac安装jee开发环境,webservice环境搭建
一.下载安装包 jdk(去官网下载) eclipse (去官网下载) tomcat(官网有9.0了)http://tomcat.apache.org/download-80.cgi#8.0.32 下载 ...
- 【线段树维护复杂状态】Ryuji doesn't want to study
https://nanti.jisuanke.com/t/31460 tree[rt].ans = tree[rt << 1].ans + tree[rt << 1 | 1]. ...
- Alpha 冲刺(4/10)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助前后端接口的开发 测试项目运行的服务器环 ...
- 60行代码:Javascript 写的俄罗斯方块游戏
哈哈这个实在是有点意思 备受打击当初用java各种类写的都要几百行啦 先看效果图: 游戏结束图: javascript实现源码: [javascript] view plaincopyprint? & ...