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;
}

猜你喜欢

转载自www.cnblogs.com/aziint/p/9100876.html