#include<bits/stdc++.h>
using namespace std;
const int maxn=(1<<16)+5;
int n,a[20],dp[maxn],sum[maxn]={0};//dp[s]表示出现s集合,可行划分的总数
int c[maxn],ispri[1700]={1,1};
int main()
{
int t,s;
scanf("%d",&t);
for(int i=0;i<16;i++) c[1<<i]=i+1;
for(int i=2;i<=850;i++)//s筛法
for(int j=i<<1;j<1700;j+=i)//<<1为两倍,三倍则+i(+比*快)
ispri[j]=1;
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
s=(1<<n)-1;
for(int i=1;i<=s;i++){//枚举集合
int li=-i&i,hi=i^li;
if(li==i) sum[i]=a[c[i]];//单个数字的组合
else sum[i]=sum[hi]+sum[li];//多个数字的组合
dp[i]=ispri[sum[i]]==0;//集合不拆分是否质数
//枚举组合状态
for(int j=hi;j>0;j=(j-1)&hi) dp[i]+=dp[j]*(ispri[sum[j^i]]==0);
}
printf("%d\n",dp[s]);
}
return 0;
}
集合划分(状压dp)
最新推荐文章于 2025-12-12 09:54:40 发布
该博客介绍了一个使用C++编写的程序,通过位运算和动态规划来解决集合划分问题,判断组合是否能形成质数。程序采用了素数筛法优化,并在每个集合状态中计算组合总数,最后输出可行划分的总数。
715

被折叠的 条评论
为什么被折叠?



