Codeforces895C Square Subsets

Description

\(n(1\le n\le 10^5)\) 个数 \(a_i(1\le a_i\le 70)\) 。求非空子集的个数,满足子集中所有的数的积是一个完全平方数。

Solution

因为 \(a_i\le 70\) ,所以我们预处理质因子。二进制 \(sta[i]\) 的第 \(j\) 位表示 \(i\) 这个数(不是 \(a_i\) )分解后是否含第 \(j\) 个质数的奇数次方。

于是 \(dp[i][j]\) 表示 \([1,i]\) 里的数取出一些乘积为状态 \(j\) 的方案数。转移见代码。

#include<bits/stdc++.h>
using namespace std;

#define N 100001 
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define ll long long

inline int read() {
	int x = 0, flag = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') flag = -1;
	for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; return x * flag;
}

const int P = 1e9 + 7;
const int prime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 };
int n, bar[75], sta[75], bin[N] = { 1 }, dp[75][(1 << 19) + 5];

int main() {
	cin >> n; rep(i, 1, n) bar[read()]++;
	rep(i, 1, 70) {
		int t = i;
		rep(j, 0, 18) while (t % prime[j] == 0) sta[i] ^= (1 << j), t /= prime[j];
	}
	rep(i, 1, n) bin[i] = (bin[i - 1] * 2) % P;
	dp[0][0] = 1;
	rep(i, 1, 70) rep(j, 0, (1 << 19) - 1)
		if (bar[i] == 0) dp[i][j] = dp[i - 1][j];
		else
			dp[i][j ^ sta[i]] = (dp[i][j ^ sta[i]] + (ll)dp[i - 1][j] * bin[bar[i] - 1]) % P,
			dp[i][j] = (dp[i][j] + (ll)dp[i - 1][j] * bin[bar[i] - 1]) % P;
	cout << dp[70][0] - 1;
	return 0;
}
posted @ 2018-05-28 16:44  aziint  阅读(113)  评论(0编辑  收藏  举报
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.