集合划分(状压DP)
Posted jpphy0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了集合划分(状压DP)相关的知识,希望对你有一定的参考价值。
问题
将n个整数分成若干组,并使得各组的数字之和为质数,求分组的方案数。
- 1 ≤ n ≤ 15 1\\leq n \\leq 15 1≤n≤15
- 整数 a i a_i ai 满足 1 ≤ a i ≤ 99 1\\leq a_i \\leq 99 1≤ai≤99
分析
代码
/* 集合划分 状压dp */
#include<bits/stdc++.h>
using namespace std;
const int MXS = (1<<15)+5;
const int MXN = 17;
int N, a[MXN], dp[MXS], sum[MXS]={0};
int c[MXS], p[1700] = {1, 1}; // 高位1的位置、是否质数
int main(){
int t, T = 0, S;
for(int i = 0; i < 15; ++i) c[1<<i] = i+1;
for(int i = 2; i*i < 1700; ++i)
for(int j = i<<1; j < 1700; j += i) p[j] = 1;
scanf("%d", &t);
while(t--){
scanf("%d", &N);
for(int i = 1; i <= N; ++i) scanf("%d", a+i);
S = (1<<N)-1;
for(int s = 1; s <= S; ++s){ // 枚举集合
int ls = -s&s, hs = s^ls;
if(ls == s) sum[s] = a[c[s]]; // 单个数字的组合
else sum[s] = sum[hs] + sum[ls]; // 多个数字的组合
dp[s] = p[sum[s]] == 0; // 集合不拆分是否质数
for(int ss = hs; ss > 0; ss = (ss-1)&hs) // 枚举组合状态
dp[s] += dp[ss]*(p[sum[ss^s]]==0);
}
printf("%d\\n", dp[(1<<N)-1]);
}
return 0;
}
以上是关于集合划分(状压DP)的主要内容,如果未能解决你的问题,请参考以下文章
Luogu4221 WC2018州区划分(状压dp+FWT)
HDU4057 Rescue the Rabbit(AC自动机+状压DP)
POJ1699 Best Sequence(AC自动机+状压DP)