C. Square Subsets
time limit per test

4 seconds

memory limit per test

256 megabytes

input

standard input

output

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.

Input

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.

Output

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.

Examples
input
4
1 1 1 1
output
15
input
4
2 2 2 2
output
7
input
5
1 2 4 5 8
output
7
Note

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的更多相关文章

  1. Codeforces Round #448 C. Square Subsets

    题目链接 Codeforces Round #448 C. Square Subsets 题解 质因数 *质因数 = 平方数,问题转化成求异或方程组解的个数 求出答案就是\(2^{自由元-1}\) , ...

  2. Codeforces 895C - Square Subsets

    895C - Square Subsets 思路:状压dp. 每个数最大到70,1到70有19个质数,给这19个质数标号,与状态中的每一位对应. 状压:一个数含有这个质因子奇数个,那么他状态的这一位是 ...

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

    题目链接  Square Subsets 这是白书原题啊 先考虑状压DP的做法 $2$到$70$总共$19$个质数,所以考虑状态压缩. 因为数据范围是$70$,那么我们统计出$2$到$70$的每个数的 ...

  4. Codeforces 828B Black Square(简单题)

    Codeforces 828B Black Square(简单题) Description Polycarp has a checkered sheet of paper of size n × m. ...

  5. CF895C: Square Subsets && 【BZOJ2844】albus就是要第一个出场

    CF895C: Square Subsets && [BZOJ2844]albus就是要第一个出场 这两道题很类似,都是线性基的计数问题,解题的核心思想也一样. CF895C Squa ...

  6. Codeforces 895C Square Subsets:状压dp【组合数结论】

    题目链接:http://codeforces.com/problemset/problem/895/C 题意: 给你n个数a[i].(n <= 10^5, 1 <= a[i] <= ...

  7. Codeforces 895C - Square Subsets 状压DP

    题意: 给了n个数,要求有几个子集使子集中元素的和为一个数的平方. 题解: 因为每个数都可以分解为质数的乘积,所有的数都小于70,所以在小于70的数中一共只有19个质数.可以使用状压DP,每一位上0表 ...

  8. Codeforces Round #448 (Div. 2)C. Square Subsets

    可以用状压dp,也可以用线型基,但是状压dp没看台懂... 线型基的重要性质 性质一:最高位1的位置互不相同 性质二:任意一个可以用这些向量组合出的向量x,组合方式唯一 性质三:线性基的任意一个子集异 ...

  9. CodeForces 1A Theatre Square

    A - Theatre Square Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u ...

随机推荐

  1. nhibernate中执行SQL语句

    在有些时候,可能需要直接执行SQL语句.存储过程等,但nhibernate并没有提供一种让我们执行SQL语句的方法,不过可以通过一些间接的方法来实现. 下面给出一个在nhibernate中执行SQL语 ...

  2. PHP 整数

    实验环境php 5.2.17,参考资料:PHP手册 1.整数溢出 如果整数超出最大范围或者运算结果超出最大范围,都会转变成float <?php $a=2147483647; var_dump( ...

  3. rest_framework组件

    认证组件 局部认证 在需要认证的视图类里加上authentication_classes = [认证组件1类名,认证组件2类名....] 示例如下: seralizers.py from rest_f ...

  4. Weighted Median

    For n elements x1, x2, ..., xn with positive integer weights w1, w2, ..., wn. The weighted median is ...

  5. 01慕课网《进击Node.js基础(一)》Node.js安装,创建例子

    版本:偶数位为稳定版本,基数为非稳定版本 - 0.6.x - 0.7.x    - 0.8.x -0.9.x    -0.10.x  -0.11.x 概念:Node.js采用谷歌浏览器的V8引擎,用C ...

  6. Python if后直接跟数字或字符串

    (1)如果if后面的条件是数字,只要这个数字不是0,python都会把它当做True处理,见下面的例子 if 15: print 'YES' 输出YES,但是如果数字是0,就会被认为是False. ( ...

  7. 让程序运行更加面向用户——电梯V2.1

    电梯V2.1 GitHub仓库地址 Problem 为程序添加命令行参数(自行利用搜索引擎进行学习). 写成 .cpp .h 文件分离的形式(大多数同学已经达到). 继续完善函数分离.模块化思想. 要 ...

  8. 扩展欧几里德 SGU 106

    题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=106   题意:求ax + by + c = 0在[x1, x2], [y1, y2 ...

  9. python处理时间相关的方法(汇总)

    记录python处理时间的模块:time模块.datetime模块和calendar模块. python版本:2.7 在介绍模块之前,先说下以下几点: 1.时间通常有这几种表示方式: a.时间戳:通常 ...

  10. (二)java.util.Scanner的使用

    Scanner是一个使用正则表达式来解析基本类型和字符串的简单文本扫描器.Scanner 使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配.然后可以使用不同的 next 方法将得到的 ...