zoukankan      html  css  js  c++  java
  • Codeforces 895C Square Subsets(状压DP 或 异或线性基)

    题目链接  Square Subsets

    这是白书原题啊

    先考虑状压DP的做法

    $2$到$70$总共$19$个质数,所以考虑状态压缩。

    因为数据范围是$70$,那么我们统计出$2$到$70$的每个数的个数然后从$2$考虑到$70$。

    设$dp[x][mask]$为考虑到$x$这个数的时候,$x$这个数和之前的所有数中,选出某些数,他们的乘积分解质因数,所有的指数对$2$取模之后,

    状态为$mask$的方案数。

    然后就可以转移了……这个状压DP花了我好几个小时……真是弱啊

    哦对最后还要特判$1$的情况。

    每个$1$选或不选都可以,然后考虑只选$1$的情况,累加即可。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    typedef long long LL;
    
    const LL mod = 1e9 + 7;
    const int N  = 3e6 + 10;
    const int M  = 1e5 + 10;
    
    int c[101], p[30], m[101];
    int n, x, cnt, now, all;
    bool flag;
    LL two[M], f[2][N];
    
    void up(LL &a, LL b) { a = (a + b) % mod;}
    
    void init(){
    	two[0] = 1;
    	rep(i, 1, 100000) two[i] = two[i - 1] * 2 % mod;
    
    	scanf("%d", &n);
    	rep(i, 1, n) scanf("%d", &x), ++c[x];
    
    	rep(i, 2, 70){
    		flag = true;
    		rep(j, 2, i - 1) if (i % j == 0){
    			flag = false;
    			break;
    		}
    		if (flag) p[cnt++] = i;
    	}
    
    	rep(i, 1, 70){
    		int y = i;
    		rep(j, 0, cnt - 1){
    			int tt = 0;
    			while (y % p[j] == 0) y /= p[j], ++tt;
    			if (tt & 1) m[i] |= (1 << j);
    		}
    	}
    }
    
    int main(){
    
    	init();
    	all = (1 << cnt) - 1;
    	rep(i, 2, 70){
    		if (c[i] == 0) continue;
    		memset(f[now ^ 1], 0, sizeof f[now ^ 1]);
    		LL a1 = two[c[i] - 1], a2 = (a1 - 1 + mod) % mod;
    
    		up(f[now ^ 1][m[i]], a1);
    		up(f[now ^ 1][0], a2);
    
    		rep(mask, 0, all) up(f[now ^ 1][mask ^ m[i]], f[now][mask] * a1 % mod);
    		rep(mask, 0, all) up(f[now ^ 1][mask], f[now][mask] * a2 % mod);
    		rep(mask, 0, all) up(f[now ^ 1][mask], f[now][mask]);
    		now ^= 1;
    	}
    
    	LL ans = f[now][0];
    	ans = (ans * two[c[1]]) % mod;
    	up(ans, (two[c[1]] - 1 + mod) % mod);
    	printf("%lld
    ", ans);
    	return 0;
    }
    

    还有一种就是考虑异或线性基的做法。

    如果一个数可以被当前线性基中的数表示出来,那么这个数就相当于一个完全平方数。

    选与不选两种状态。

    令最后线性基中的数的个数为$x$

    最后答案就是$2^{n - x} - 1$

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    const int mod = 1e9 + 7;
    
    int c[101], p[30], m[101], b[100010];
    int n, x, cnt, now, all;
    int ans = 0;
    int ret;
    bool flag;
    
    struct lb{
    	int d[70];
    	int cnt;
    	void clear(){
    		memset(d, 0, sizeof d);
    		cnt = 0;
    	}
    	bool ins(int val){
    		dec(i, 30, 0) if (val & (1 << i)){
    			if (!d[i]){ d[i] = val; break; }
    			val ^= d[i];
    		}
    		return val > 0;
    	}
    	int qmax(){
    		int ret = 0;
    		dec(i, 30, 0) if ((ret ^ d[i]) > ret) ret ^= d[i];
    		return ret;
    	}
    	int qmin(){
    		rep(i, 0, 30) if (d[i]) return d[i];
    		return 0;
    	}
    } LB;
    
    
    void init(){
    
    	scanf("%d", &n);
    	rep(i, 1, n) scanf("%d", b + i), ++c[x];
    
    	rep(i, 2, 70){
    		flag = true;
    		rep(j, 2, i - 1) if (i % j == 0){
    			flag = false;
    			break;
    		}
    		if (flag) p[cnt++] = i;
    	}
    
    	rep(i, 1, 70){
    		int y = i;
    		rep(j, 0, cnt - 1){
    			int tt = 0;
    			while (y % p[j] == 0) y /= p[j], ++tt;
    			if (tt & 1) m[i] |= (1 << j);
    		}
    	}
    }
    
    int main(){
    
    	init();
    	rep(i, 1, n) LB.ins(m[b[i]]);
    	rep(i, 0, 30) if (LB.d[i]) ++ans;
    	ret = 1;
    	rep(i, 1, n - ans) ret = ret * 2 % mod;
    	ret += mod - 1;
    	ret %= mod;
    	printf("%d
    ", ret);
    	return 0;
    }
    
  • 相关阅读:
    用c++写一个广告系统
    zookeeper学习系列:四、Paxos算法和zookeeper的关系
    zookeeper学习系列:三、利用zookeeper做选举和锁
    zookeeper学习系列:二、api实践
    zookeeper学习系列:一、入门
    HBase Cassandra Riak HyperTable
    困扰我多年的Connection reset问题
    scala学习笔记
    ImageMagick and JMagick install on Mac OSX
    jersey处理支付宝异步回调通知的问题:java.lang.IllegalArgumentException: Error parsing media type 'application/x-www-form-urlencoded; text/html; charset=UTF-8'
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/8004857.html
Copyright © 2011-2022 走看看