P5933 [清华集训2012] 串珠子

P5933 [清华集训2012] 串珠子 题解

Link
非常好的一道状压题目(为啥自己总是想不到呢……)。
首先我们发现 n 很小,于是考虑状压。我们一开始肯定会设 dps 为集合 s 内的点相互连通的方案数。但是,我们发现,这个东西非常不好算,而且难以转移。于是……
!

没错,内部点连边的方案数很显然,我们只需要算出内部点不连通的方案,然后减走就行了。

其实,我们发现,内部连通的方案数之所以难算,就是因为只需要一条边就可以连通,方案之间的界限是模糊的;而如果不连通,我们只需要规定哪两部分不连通就行了。

因此,我们有了这样一个方案。我们现在要计算 s 的答案 dps,那么就从一个点开始,不断扩展点集(或者更准确的说,去枚举包含这个点的点集),答案就是这个点集内部连通的方案数与他在 s 中的补集的连边方案数。这样做的含义就是,保证一个点集内部连通,然后割断它与其补集的连边,补集内部随意连边。我们来考虑这样做的正确性。每次扩展(或更换)点集都是在增加强制连通的点,而这些点与点集之外都是强制割裂的,也就是说,只要这些点集不重复,那么他们与外界的联系也是不重复的,最终结果也是不会重复的。

关于具体实现,首先要钦定一个点 ps,并枚举 ps 中的补集 Csp (C 为补集符号)的子集 subs,有 dps=subsCspfsubs×dpCssubs。这里需要注意,subsCssubs 的位置不能互换,因为这里的 p 点就是最初的基准点,Cssubs 是围绕这一点不断变化和扩展的,如果交换,则会算重。这里建议通过小样例手动模拟一下来理解。

代码(蛮乱的):

#include<bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
const int N = 20;
const int NN = 70000;
inline int read(){
int x = 0; char ch = getchar();
while(ch<'0' || ch>'9') ch = getchar();
while(ch>='0'&&ch<='9') x = x*10+ch-48, ch = getchar();
return x;
}
inline int fpow(int a, int b){
int ret = 1;
a%=mod;
while(b){
if(b & 1){
ret = (1ll*ret*a)%mod;
}
a = (1ll*a*a)%mod;
b>>=1;
}
return ret;
}
int c[N][N];
int n;
int f[NN];
int dp[NN];
int main(){
n = read();
for(int i = 1; i<=n; ++i){
for(int j = 1; j<=n; ++j){
c[i][j] = read();
}
}
for(int s = 1; s<=(1<<n)-1; ++s){
f[s] = 1;
for(int i = 1; i<=n; ++i){
if((s>>(i-1))&1){
for(int j = i+1; j<=n; ++j){
if((s>>(j-1))&1){
f[s] = (1ll*(c[i][j]+1)*f[s])%mod;
}
}
}
}
}
for(int s = 1; s<=(1<<n)-1; ++s){
int tmp;
// for(int i = 1; i<=n; ++i){
// if((s>>(i-1))&1){
// tmp = (1<<(i-1));
// break;
// }
// }
for(int i = n; i>=1; --i){
if((s>>(i-1))&1){
tmp = (1<<(i-1));
break;
}
}
int ts = s^tmp;
int Cs = 0;
for(int subs = ts; subs; subs = ts&(subs-1)){
Cs = (1ll*Cs+1ll*f[subs]*dp[s^subs]%mod)%mod;
}
// cout << Cs << " ";
dp[s] = ((f[s]-Cs)%mod+mod)%mod;
// Cs = 0;
// for(int subs = ts; subs; subs = ts&(subs-1)){
// Cs = (1ll*Cs+1ll*f[s^subs]*dp[subs]%mod)%mod;
// }
// cout << Cs << endl;
}
printf("%d\n", dp[(1<<n)-1]);
return 0;
}
posted @   霜木_Atomic  阅读(24)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示