首页 > 其他分享 >P5933 [清华集训2012] 串珠子

P5933 [清华集训2012] 串珠子

时间:2023-07-21 21:34:48浏览次数:42  
标签:连通 ch P5933 int 补集 点集 集训 dp 2012

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

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

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

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

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

关于具体实现,首先要钦定一个点 \(p \in s\),并枚举 \(p\) 在 \(s\) 中的补集 \(C_sp\) (\(C\) 为补集符号)的子集 \(subs\),有 \(dp_s = \sum_{subs \in C_sp} f_{subs} \times dp_{C_ssubs}\)。这里需要注意,\(subs\) 与 \(C_ssubs\) 的位置不能互换,因为这里的 \(p\) 点就是最初的基准点,\(C_ssubs\) 是围绕这一点不断变化和扩展的,如果交换,则会算重。这里建议通过小样例手动模拟一下来理解。

代码(蛮乱的):

#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;
}

标签:连通,ch,P5933,int,补集,点集,集训,dp,2012
From: https://www.cnblogs.com/frostwood/p/17572431.html

相关文章

  • 2023 暑假集训模拟赛题解
    目录CSP模拟1CSP模拟2FSYOCSP模拟1来自学长的馈赠2.CSP模拟2F考虑\(x\)只能在\(a_1\oplusb_i\)里选,那么分别代入暴力检验即可.时间复杂度\(\tilde\Theta(n^2)\),可以通过.S考虑交换同色的部分一定不优,所以同色字符的相对位置一定是不变的.那么操作序列......
  • 20230721巴蜀暑期集训测试总结
    T1似乎想复杂了。搓了一个\(O(Q\sqrt{n\logn})\)的做法,成功跳过正解。结果考后发现普通分块就可以\(O(Q\sqrtn)\)。而且似乎还WA了一些点。根据题意可以发现\(b_i\)为\(1\)当且仅当\(i\)在二进制下有奇数个\(1\)。这个可以用来快速求\(b_i\)。再观察性质,发现\(......
  • 集训总结(经常鸽)
    7.13今天上午主要是把cdq和treap复习了一下,顺便写了两个博客来记录。下午一直在学斜率优化,先是学了单调队列优化,写了 【P4954[USACO09OPEN]TowerofHayG】【P2254[NOI2005]瑰丽华尔兹】然后就开始学斜率优化,学完之后写了【P3628[APIO2010]特别行动队】这道题真正......
  • Luogu 6821 PA2012 Tanie linie
    这里只讲加强版,这是严格弱化。结论是贪心。每次取出最大和连续子段,目前答案加上这个子段和,然后再把这个子段取反(相反数T),然后求整个过程答案的最大值。考虑费用流模型。对于\(i\len\),\(S\toi\)连边,\(i\toT\)连边,流量为\(1\)费用为\(0\);\(i\toi+1\)连边,流量为\(1\)费......
  • 七月份集训总结
    七月份集训总结前言今天被拉到办公室里头一个个总结了一下集训的收获和感想。emm,是该总结总结了。感想自己马上就要从准高二成为真正的高二学生了,时间真的蛮快的。不知道去年的霜木看到今天的自己,还会不会选择竞赛呢?收获&不足平衡树的一些应用KD-Tree(目前只会静态的模板......
  • 2023夏季集训D1-贪心二分
    2023夏季集训D1贪心二分0x00前言24OIFXJ大佬来给我们讲课OrzOrz.讲课好难TAT.0x10贪心0x11经典贪心写了BestCowLineG/S和田忌赛马一位小伙从同学那里要来了一份BestCow代码Debug但没有发现代码没有输入,这是他思路3小时后发生的hack.田忌赛马太......
  • 暑假集训随笔2 主席树/二维树状数组
    P4514上帝造题的七分钟题意维护对二维平面上的矩形区域各元素进行加法以及对矩形区域求和链接:https://www.luogu.com.cn/problem/P4514思路通过二维树状数组维护的二维前缀和利用差分实现矩形区域的区间加法与区间求和。具体而言,二维的前缀和可以仿照一维的前缀和进行定义......
  • 20230719巴蜀暑期集训测试总结
    T1赛时打了一个\(O(n^3)\)\(16pts\)暴力和一个似乎可以过一个\(20pts\)特殊性质但其余无正确性的贪心。结果出来发现特殊性质挂了一个点,另一个地方还莫名其妙对了。说明特殊性质挂掉了,如果运气不好可能就挂到\(16pts\)了。考后看题解发现\(O(n^2)\)其实也是不难想的,有点......
  • 第7章 Windows Server 2012中的Active Directory
    第7章WindowsServer2012中的ActiveDirectory7.1ActiveDirectory基础知识简介在开始讨论ActiveDirectory之前,先介绍一些基础知识。由于ActiveDirectory使用很多特有的词汇,这里只解释管理员需要了解的那部分。工作组工作组是一个Windows网络(LAN)中的一台或名多台......
  • 第6章 Windows Server 2012 R2 中的DNS和名称解析
    第6章WindowsServer2012R2中的DNS和名称解析6.1理解DNS服务器角色下面简单总结本章涉及的DNS基本概念主机名指(用户友好)的计算机的名称,根据DNS标准,主机名可以多达255个字符,主机名等价于计算机的名字。名称空间这是域的名称,并不是具体指ActiveDirectory域......