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. HIVE中的数据怎么导出到hdfs或本地呢

    思路一:重定向 在我不知道工具 ,也不熟悉HIQL语法的情况下,没办法了,只有选择一个最简单粗暴的方法,重定向. 在shell中使用 hive -e 可以在shell中执行hive命令,hive -f ...

  2. Vyatta 网络操作系统

    原文发表于:2010-09-19 转载至cu于:2012-07-21 以下是"开源中国社区"写到的: http://www.oschina.net/news/11423/vyatt ...

  3. 笔试题:C++打印队列

    题目:打印队列 题目介绍:现在用打印机打印队列,已知打印任务有9个优先级(1-9),现在给出一系列任务,求输出打印顺序(任务下标,从0开始). 例: 输入:9,3,5,4,7,1 输出:0,4,2,3 ...

  4. wireshark解析https协议方法

    本文仅介绍通过协商密钥的方式实现https解析的方法 wireshark支持pem

  5. Hybrid APP基础篇(四)->JSBridge的原理

    说明 JSBridge实现原理 目录 前言 参考来源 前置技术要求 楔子 原理概述 简介 url scheme介绍 实现流程 实现思路 第一步:设计出一个Native与JS交互的全局桥对象 第二步:J ...

  6. Java 学习笔记 ------第四章 认识对象

    本章学习目标: 区分基本类型与类类型 了解对象与参考的关系 从打包器认识对象 以对象观点看待数组 认识字符串的特性 一."=" 和 "==" 当=用于基本类型时 ...

  7. Python语言基础

    一.Python简介 Python是跨平台动态语言 特点:优雅.明确.简单 适用:web网站和网络服务:系统工具和脚步:包装其他语言开发的模块 不适用:贴近硬件(首选C):移动开发:IOS/Andro ...

  8. Python:字典操作总结

     字典是Python中唯一的映射类型 [注]:字典中数据是无序排放的 一.字典的创建方法 方法1:用大括号包裹键值对从而创建字典 addict={}#创建一个空字典 addict={key1:valu ...

  9. 关于“问吧APP”问卷调查报告分析与体会

         上周根据我们走廊奔跑队的“问吧APP”项目对本校范围内的学生发放了上百份调查问卷,并对此作出了统计和整理.针对我们项目所提出的问题涉及到的用户信息有性别.年龄.学历.职业.平时上网途径以及对 ...

  10. fsockopen 异步非阻塞式请求数据

    index.php <?php ini_set ( "max_execution_time", "0" ); // 要传递的数据 $form_data = ...