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. Vue2 v-bind:href 中如何使用过滤器

    <a class="topic_title" v-bind:href="info.id|getTitleHref" v-bind:title=" ...

  2. 《More Effective C++ 》读书笔记(二)Exception 异常

    这事篇读书笔记,只记录自己的理解和总结,一般情况不对其举例子具体说明,因为那正是书本身做的事情,我的笔记作为梳理和复习之用,划重点.我推荐学C++的人都好好读一遍Effective C++ 系列,真是 ...

  3. Paper Reading - Long-term Recurrent Convolutional Networks for Visual Recognition and Description ( CVPR 2015 )

    Link of the Paper: https://arxiv.org/abs/1411.4389 Main Points: A novel Recurrent Convolutional Arch ...

  4. javascript中的取反再取反~~

    操作符~, 是按位取反的意思,表面上~~(取反再取反)没有意义,实际上在JS中可以将浮点数变成整数. <html> <script> var myArray = new Arr ...

  5. Java反编译插件

    一.eclipse->help->Eclipse Marketplace 如下图:搜索JadClipse,install进行下载安装,

  6. Scrum立会报告+燃尽图(Beta阶段第二周第七次)

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2415 项目地址:https://coding.net/u/wuyy694 ...

  7. 探路者 Alpha阶段中间产物

     版本控制 git地址:https://git.coding.net/clairewyd/toReadSnake.git   贪吃蛇(单词版)软件功能说明书 1 开发背景 “贪吃蛇”这个游戏对于80, ...

  8. Macbook Pro开机黑屏了。

    问题描述:点了appstore的更新,然后重启黑屏.(说明:黑屏是屏幕没亮:灰屏是屏幕亮了是灰黑色的.) 黑屏问题大,灰屏问题小. 开机按option没反应的跳到步骤四 一.数据 苹果电脑黑屏了,想搞 ...

  9. 201621123037 《Java程序设计》第8周学习总结

    作业08-集合 1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 答: 思维导图: 其他-笔记: 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayLi ...

  10. Kotlint集合简单总结

    1.数组操作 var testArray = Array<>("s","ss")或者 = arrayOf("s","s ...