codeforces 895C Square Subsets 线性基 或 状压DP
2017-11-27 06:24
411 查看
简略题意:n个数,问有多少选择的方法能够使得这些数的乘积变成完全平方数。
把每个数唯一分解之后,用其质因子以及其对应的幂来表示这个数。如果若干个数乘积想要位完全平方数,那么势必要使得相乘后的每一个质数的幂为偶数。
那么我们选择这个数的时候只需要在意他的所有质因子的幂次的奇偶性即可。
因为数的大小只有70,至多只会有19种质因子,可以状态压缩。因此如果一个数的质因子的幂次为奇数,就可以用1来表示对应位。
我们现在就是想取若干个数相乘使得每个质因子的幂次都为偶数,而%2意义下的加法是异或运算。
原问题转变成了从n个数中选取若干个数使得他们的异或值变为0的方案数,这就是经典的线性基问题。
那么我们可以得到一个n * 19大小的矩阵,只需要算出这个矩阵的秩,即为线性无关组的大小(线性基的大小)x,那么自由变元的大小即为n - x。
方案数即为2n−x−1,减1是因为不允许选空集。
找什么最大线性无关组啊?
70个数,(1<<19)的状态,记录下个数直接DP啊?
把每个数唯一分解之后,用其质因子以及其对应的幂来表示这个数。如果若干个数乘积想要位完全平方数,那么势必要使得相乘后的每一个质数的幂为偶数。
那么我们选择这个数的时候只需要在意他的所有质因子的幂次的奇偶性即可。
因为数的大小只有70,至多只会有19种质因子,可以状态压缩。因此如果一个数的质因子的幂次为奇数,就可以用1来表示对应位。
我们现在就是想取若干个数相乘使得每个质因子的幂次都为偶数,而%2意义下的加法是异或运算。
原问题转变成了从n个数中选取若干个数使得他们的异或值变为0的方案数,这就是经典的线性基问题。
那么我们可以得到一个n * 19大小的矩阵,只需要算出这个矩阵的秩,即为线性无关组的大小(线性基的大小)x,那么自由变元的大小即为n - x。
方案数即为2n−x−1,减1是因为不允许选空集。
#define others #ifdef poj #include <iostream> #include <cstring> #include <cmath> #include <cstdio> #include <algorithm> #include <vector> #include <string> #endif // poj #ifdef others #include <bits/stdc++.h> #endif // others //#define file #define all(x) x.begin(), x.end() using namespace std; const double eps = 1e-8; int dcmp(double x) { if(fabs(x)<=eps) return 0; return (x>0)?1:-1;}; typedef long long LL; namespace solver { int n; const LL maxn = 110000; const LL mod = 1e9+7; int a[maxn]; bool isp(int x) { if(x <= 1) return 0; for(int i = 2; i <= sqrt(x); i++) if(x % i == 0) return 0; return 1; } vector<int> p, base; void solve() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); } for(int i = 1; i <= 70; i++) if(isp(i)) p.push_back(i); for(int i = 1; i <= n; i++) { int val = 0; for(int j = 0; j < p.size(); j++) { int v = a[i]; int cnt = 0; while(v % p[j] == 0) { cnt++; v /= p[j]; } if(cnt & 1) val |= 1 << j; } for(int j = 0; j < base.size(); j++) val = min(val, val ^ base[j]); if(val) base.push_back(val); } LL ans = 1; for(int i = 0; i < n - base.size(); i++) { ans *= 2, ans %= mod; } cout<<(ans-1)<<endl; } } int main() { #ifdef file freopen("gangsters.in", "r", stdin); freopen("gangsters.out", "w", stdout); #endif // file solver::solve(); return 0; }
找什么最大线性无关组啊?
70个数,(1<<19)的状态,记录下个数直接DP啊?
#define others #ifdef poj #include <iostream> #include <cstring> #include <cmath> #include <cstdio> #include <algorithm> #include <vector> #include <string> #endif // poj #ifdef others #include <bits/stdc++.h> #endif // others //#define file #define all(x) x.begin(), x.end() using namespace std; const double eps = 1e-8; int dcmp(double x) { if(fabs(x)<=eps) return 0; return (x>0)?1:-1;}; typedef long long LL; namespace solver { LL n; const LL mod = 1e9+7; const LL maxn = 110000; LL v[maxn]; LL pow2[maxn]; bool isp(LL x) { if(x <= 1) return 0; for(LL i = 2; i <= sqrt(x); i++) if(x % i == 0) return 0; return 1; } vector<LL> p; LL sta[maxn]; LL dp[2][(1<<20)]; LL sum[77]; void solve() { scanf("%d", &n); for(LL i = 1; i <= n; i++) { scanf("%d", &v[i]); } for(LL i = 1; i <= 70; i++) if(isp(i)) p.push_back(i); for(LL i = 1; i <= n; i++) { sum[v[i]] ++; for(LL j = 0; j < p.size(); j++) { LL val = v[i]; LL cnt = 0; while(val % p[j] == 0) { cnt++; val /= p[j]; } if(cnt & 1) sta[v[i]] |= (1 << j); } } pow2[0] = 1; for(LL i = 1; i < maxn; i++) pow2[i] = pow2[i-1] * 2 % mod; dp[0][0] = 1; for(LL i = 1; i <= 70; i++) { int now = i & 1, pre = now ^ 1; memset(dp[now], 0,sizeof dp[now]); for(LL j = 0; j < (1 << 19); j++) { if(sum[i] == 0) { dp[now][j] = dp[pre][j]; } else { LL v = pow2[sum[i]-1]; dp[now][j] += v * dp[pre][j]; if(dp[now][j] >= mod) dp[now][j] %= mod; dp[now][j] += v * dp[pre][j^sta[i]]; if(dp[now][j] >= mod) dp[now][j] %= mod; } } } cout<<dp[0][0]-1<<endl; } } int main() { #ifdef file freopen("gangsters.in", "r", stdin); freopen("gangsters.out", "w", stdout); #endif // file solver::solve(); return 0; }
相关文章推荐
- CodeForces 895 C.Square Subsets(状压DP+线性基)
- codeforces 895C Square Subsets
- 895C - Square Subsets 状压DP
- codeforces 895C
- Codeforces 938G Shortest Path Queries 线段树分治+并查集+线性基
- CodeForces 587E Duff as a Queen (线段树+线性基)
- Codeforces 16E Fish (状压dp+概率)
- [无向图简单环计数 状压DP] Codeforces 11D Beta Round #11 D. A Simple Task
- Codeforces 678E Another Sith Tournament(状压dp,概率dp)
- Codeforces 453B Little Pony and Harmony Chest 状压DP
- CodeForces 599E Sandy and Nuts 状压DP
- CodeForces 724 G.Xor-matic Number of the Graph(组合数学+dfs+线性基)
- [数位DP][线性基]Codeforces 388D. Fox and Perfect Sets
- Codeforces Round #448 (Div. 2): C. Square Subsets(线性基)
- cf CodeForces - 165E 【状压dp】
- CodeForces 165E 【状压DP】
- CodeForces - 11D 【状压DP+无向图找环】
- cf 895C Square Subsets
- Codeforces 895C
- [状压DP || 容斥 矩阵树定理] Codeforces 53E. Dead Ends