【竞赛图】【DP】最长路径


分析:

很显然,最长路径一定是唯一的。

考虑这么证明:对终点v而言,所有不在路径上的点一定指向它。
然后,对于次终的点u而言,如果它指向任意一个不在路径上的点,那么可以通过u->x->v,得到一条更长的路径,所以所有不在路径上的点也一定指向它
……
综上,除了最长路径以外,所有点都指向这条路径。

那么,就可以DP了

定义DP(i,j)DP(i,j)表示:i个点的竞赛图,构成最长长度为j的路径的方案数。

显然,对于不在路径上的点,其两两之间任意连边均可,唯一要考虑的就是路径上的点。

因此,i>j若i>j,DP(i,j)=DP(j,j)2C(ij,2)DP(i,j)=DP(j,j)*2^{C(i-j,2)}

现在就是当i=ji=j时怎么办,很显然,对于一个i个点的图,合法的jj满足0ji0\leq j\leq i,因此,可以用一下容斥:即总方案数(2(C(i,2)))(2^{(C(i,2))}),减去所有j<ij<i的DP值,就可以得到DP(i,i)DP(i,i)的值。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define SF scanf
#define PF printf
#define MAXN 2010
using namespace std;
typedef long long ll;
ll C[MAXN][MAXN],dp[MAXN][MAXN];
ll MOD;
void prepare(int n){
	C[0][0]=1;
	for(int i=1;i<=n;i++){
		C[i][0]=1;
		for(int j=1;j<=i;j++)
			C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;	
	}
}
ll fsp(ll x,ll y){
	ll res=1;
	while(y){
		if(y&1ll)
			res=res*x%MOD;
		x=x*x%MOD;
		y>>=1ll;	
	}
	return res;
}
int main(){
	freopen("path.in","r",stdin);
	freopen("path.out","w",stdout);
	int n;
	SF("%d%d",&n,&MOD);
	prepare(n);
	for(ll i=1;i<=n;i++){
		ll sum=0;
		for(ll j=1;j<i;j++){
			dp[i][j]=C[i-1][j-1]*dp[j][j]%MOD*fsp(2,(i-j)*(i-j-1)/2ll)%MOD;
			(sum+=dp[i][j])%=MOD;
//			PF("[%d %d :%lld]\n",i,j,dp[i][j]);
		}
		dp[i][i]=(fsp(2,i*(i-1ll)/2ll)-sum+MOD)%MOD;
//		PF("[%d %d :%lld]\n",i,i,dp[i][i]);
	}
	for(int i=1;i<=n;i++)
		PF("%lld\n",dp[n][i]);
}

相关文章:

  • 2022-12-23
  • 2021-12-12
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-03-07
  • 2022-12-23
猜你喜欢
  • 2021-06-07
  • 2021-11-04
  • 2022-12-23
  • 2021-05-28
  • 2022-12-23
  • 2021-10-21
  • 2022-12-23
相关资源
相似解决方案