题目链接  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\n", 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\n", ret);
return 0;
}

Codeforces 895C Square Subsets(状压DP 或 异或线性基)的更多相关文章

  1. Codeforces 895C - Square Subsets 状压DP

    题意: 给了n个数,要求有几个子集使子集中元素的和为一个数的平方. 题解: 因为每个数都可以分解为质数的乘积,所有的数都小于70,所以在小于70的数中一共只有19个质数.可以使用状压DP,每一位上0表 ...

  2. Codeforces 895C - Square Subsets

    895C - Square Subsets 思路:状压dp. 每个数最大到70,1到70有19个质数,给这19个质数标号,与状态中的每一位对应. 状压:一个数含有这个质因子奇数个,那么他状态的这一位是 ...

  3. codeforces Diagrams & Tableaux1 (状压DP)

    http://codeforces.com/gym/100405 D题 题在pdf里 codeforces.com/gym/100405/attachments/download/2331/20132 ...

  4. Codeforces 917C - Pollywog(状压 dp+矩阵优化)

    UPD 2021.4.9:修了个 typo,为啥写题解老出现 typo 啊( Codeforces 题目传送门 & 洛谷题目传送门 这是一道 *2900 的 D1C,不过还是被我想出来了 u1 ...

  5. Codeforces 79D - Password(状压 dp+差分转化)

    Codeforces 题目传送门 & 洛谷题目传送门 一个远古场的 *2800,在现在看来大概 *2600 左右罢( 不过我写这篇题解的原因大概是因为这题教会了我一个套路罢( 首先注意到每次翻 ...

  6. Codeforces 544E Remembering Strings 状压dp

    题目链接 题意: 给定n个长度均为m的字符串 以下n行给出字符串 以下n*m的矩阵表示把相应的字母改动成其它字母的花费. 问: 对于一个字符串,若它是easy to remembering 当 它存在 ...

  7. codeforces 21D. Traveling Graph 状压dp

    题目链接 题目大意: 给一个无向图, n个点m条边, 每条边有权值, 问你从1出发, 每条边至少走一次, 最终回到点1. 所走的距离最短是多少. 如果这个图是一个欧拉回路, 即所有点的度数为偶数. 那 ...

  8. CodeForces 327E Axis Walking(状压DP+卡常技巧)

    Iahub wants to meet his girlfriend Iahubina. They both live in Ox axis (the horizontal axis). Iahub ...

  9. Codeforces ----- Kefa and Dishes [状压dp]

    题目传送门:580D 题目大意:给你n道菜以及每道菜一个权值,k个条件,即第y道菜在第x道后马上吃有z的附加值,求从中取m道菜的最大权值 看到这道题,我们会想到去枚举,但是很显然这是会超时的,再一看数 ...

随机推荐

  1. jQuery将物体居中,并且转换显示和隐藏

    今天来给大家贴一段代码,代码的作用就是利用jQuery将物体居中,并且转换显示和隐藏: 首先建立一个div标签并且写好css样式,具体如下 然后我想要的效果是当我点击了button这个按钮,test可 ...

  2. Ubuntu 16.04系统安装步骤

    1.安装系统 2.设置更新源,自动检测最优更新源 3.关闭自动更新 4.设置终端样式 5.设置终端快捷键 6.安装vim,配置.vimrc 7.修改.bashrc第62行,小写w为大写W,设置终端不显 ...

  3. python爬虫集合

    逐渐也写了有二十余篇博文,内容一多就导致有些内容不能够方便快捷定位. 虽然博客有标签进行分类,实际查找时也并不如做一个同类文章的集合来得直观. 这里就对python爬虫相关博文做个集合: 爬虫基础知识 ...

  4. 数据结构和算法(What Why How)

    数据结构和算法是什么? 从广义上讲,数据结构就是指一组数据的存储结构.算法就是操作数据的一组方法. 从狭义上讲,是指某些著名的数据结构和算法,比如队列.堆.栈.二分查找.动态规划等. 数据结构和算法有 ...

  5. hdu2604 递推转换矩阵快速幂

    刚开始还以为用位运算与或几下几个循环就搞定了,算着算着发现不行........ 还是一种固定的切题角度,我假设有长度为n,总的排列数位f(n),怎么算他呢?从后往前考虑,因为大多数情况,都是用前面的结 ...

  6. Activity树图

  7. Leetcode 466.统计重复个数

    统计重复个数 定义由 n 个连接的字符串 s 组成字符串 S,即 S = [s,n].例如,["abc", 3]="abcabcabc". 另一方面,如果我们可 ...

  8. TOJ3031: Multiple bfs

    3031: Multiple Time Limit(Common/Java):2000MS/6000MS     Memory Limit:65536KByte Total Submit: 60   ...

  9. 当网络中断的时候,JTA全局事务管理,究竟会不会回滚???

    前言:有人问了我一个问题,就是说在网络中断的时候,JTA的全局事务管理,会不会回滚?当时说会回滚,但没给对方说清楚理由,也不太认同我的观点.现在总结一下. 今天一天都在看文档(也查了一些博客和网站), ...

  10. API生命周期第二阶段——设计:采用swagger进行API描述、设计

    本篇博客主要是以swagger为依托,介绍API生命周期的第二个阶段--设计!在详细介绍之前,我必须声明一点:如果是想了解swagger和项目框架的集成的,这里没有.我要介绍的swagger进行的AP ...