Codeforces Round #448 (Div. 2): C. Square Subsets(线性基)

来源:互联网 发布:魔兽世界 mac版 cruse 编辑:程序博客网 时间:2024/06/06 13:05

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
41 1 1 1
output
15
input
42 2 2 2
output
7
input
51 2 4 5 8
output
7


会线性基的话,这题就是5分钟题

不然要想很久+码很久的状压DP,或者卡到比赛结束


题意:

给你n个数,每个数<=70,问有多少个集合,满足集合中所有数相乘是个完全平方数(空集除外)


思路:

很容易想到的是:一个完全平方数分解质因数后所有的因子一定都出现偶数次,而这题的ai<=70

小于70的质数有且只有19个,这样就可以将每个数转成一个长度为19的二进制

第i位为1就说明分解质因数后第i个质数出现了奇数次,为0即出现偶数次,之后再把它转回十进制的另一个数

这样问题就变成了n个数,有多少个集合满足它们异或为0!


求出这n个数的线性基,答案就是2^(n-线性基内数的个数)-1

可以用高斯消元证明

#include<stdio.h>#define mod 1000000007#define LL long longint a[100005], p[21];int z[21] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67};LL Pow(LL x, int y){LL ans = 1;while(y){if(y%2)ans = ans*x%mod;x = x*x%mod;y /= 2;}return ans;}int main(void){int n, i, x, j, now, sum;scanf("%d", &n);for(i=1;i<=n;i++){scanf("%d", &x);for(j=0;j<=18;j++){now = 0;while(x%z[j]==0)x /= z[j], now ^= 1;a[i] |= now*(1<<j);}}for(i=1;i<=n;i++){for(j=18;j>=0;j--){if(a[i]&(1<<j)){if(p[j]==0){p[j] = a[i];break;}elsea[i] ^= p[j];}}}sum = n;for(j=0;j<=18;j++){if(p[j])sum--;}printf("%lld\n", Pow(2ll, sum)-1);return 0;}


阅读全文
1 0