[JXOI2012]奇怪的道路

XXXVII.[JXOI2012]奇怪的道路

神题。

(为以示区别,题面中的\(k\)我们称作\(p\))。

思路1.

观察到\(k\)很小,考虑状压。

\(f[i][j][k]\)表示:

\(i\)个位置的边已经全部连完了,位置\([i-p+1,i]\)的状态压起来是\(j\),并且连了\(k\)条边的方案数。

代码:

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int f[50][1<<10][50],n,m,lim,p;
int ksm(int x,int y){
	int z=1;
	for(;y;x=(1ll*x*x)%mod,y>>=1)if(y&1)z=(1ll*z*x)%mod;
	return z;
}
int main(){
	scanf("%d%d%d",&n,&m,&p),lim=1<<p;
	f[0][0][0]=1;
	for(int i=0;i<n;i++)for(int j=0;j<min(1<<i,lim);j++)for(int k=0;k<=m;k++){
		if(!f[i][j][k])continue;
		for(int g=0;g<min(1<<(i+1),lim);g++){
			int diff=((g>>1)^j);
			if(__builtin_parity(diff)!=(g&1))continue;
			int cnt=__builtin_popcount(diff);
			for(int h=k+cnt;h<=m;h+=2)(f[i+1][g][h]+=1ll*f[i][j][k]*ksm(min(i,p),(h-k-cnt)>>1)%mod)%=mod;
		}
	}
//	for(int i=1;i<=n;i++)for(int j=0;j<min(1<<i,lim);j++)for(int k=0;k<=m;k++)printf("%d,%d,%d:%d\n",i,j,k,f[i][j][k]);
	printf("%d\n",f[n][0][m]);
	return 0;
}

一交,WA,\(45\%\)

咋肥事?

因为这么连,会有重复计算的部分(因为边是无序的,同一组边集只不过因为顺序不同就会加不止一次)。

思路2.

为了凸显顺序,我们不得不考虑再增加一维。

\(f[i][j][k][l]\)表示:

\(i\)个位置的边已经全部连完了,连了\(k\)条边,位置\([i-p+1,i+1]\)的状态压起来是\(j\),并且位置\(i+1\)只与\([i-p+1,i-l]\)里的点连了边的方案数。

显然,初始\(f[1][0][0][0]=1\),答案是\(f[n][m][0][0]\)

考虑如何转移(刷表法)。

  1. 我们再连一条边\((i-l-1,i+1)\)

\(f[i][j+1][k\operatorname{xor}2^0\operatorname{xor}2^l][l]+=f[i][j][k][l]\)

  1. 连接\((i-l-1,i+1)\)之间的边已经全部连完,来到下一位。

\(f[i][j][k][l+1]+=f[i][j][k][l]\)

  1. \(l\)枚举完成后,

如果有\(k\)的第\(p\)位为\(0\),则可以转移到下一位,则有

\(d[i+1][j][k<<1][\min(i,p)]+=f[i][j][k][0]\)

复杂度\(O(nmp2^p)\)

代码:

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int n,m,p,f[40][40][1<<10][10],lim;
int main(){
	scanf("%d%d%d",&n,&m,&p),lim=(1<<(p+1));
	f[1][0][0][0]=1;
	for(int i=1;i<=n;i++)for(int j=0;j<=m;j++)for(int k=0;k<lim;k++){
		for(int l=min(i-1,p);l;l--){
			if(j<m)(f[i][j+1][k^(1<<l)^1][l]+=f[i][j][k][l])%=mod;
			(f[i][j][k][l-1]+=f[i][j][k][l])%=mod;	
		}
		if(!(k&(1<<p)))(f[i+1][j][k<<1][min(i,p)]+=f[i][j][k][0])%=mod;
	}
	printf("%d\n",f[n][m][0][0]);
	return 0;
}

原文地址:https://www.cnblogs.com/Troverld/p/14597187.html