luogu P2051 [AHOI2009]中国象棋 dp 状态压缩+容斥
Posted qingyuyyyyy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P2051 [AHOI2009]中国象棋 dp 状态压缩+容斥相关的知识,希望对你有一定的参考价值。
参考:https://www.luogu.com.cn/blog/RPdreamer/p2051
#include<map> #include<queue> #include<time.h> #include<limits.h> #include<cmath> #include<ostream> #include<iterator> #include<set> #include<stack> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep_1(i,m,n) for(int i=m;i<=n;i++) #define mem(st) memset(st,0,sizeof st) inline int read() { int num=0, w=0; char ch=0; while (!isdigit(ch)) { w|=ch==‘-‘; ch = getchar(); } while (isdigit(ch)) { num = (num<<3) + (num<<1) + (ch^48); ch = getchar(); } return w? -num: num; } typedef long long ll; typedef pair<int,int> pii; typedef unsigned long long ull; typedef pair<double,double> pdd; const int inf = 0x3f3f3f3f; const int mod=9999973; const int N=110; #define int ll int f[N][N][N]; //f[i][j][k]代表放了前i行,有j列是有一个棋子,有k列是有2个棋子的合法方案数. inline int C(int x) { return ((x*(x-1))/2)%mod; } ll n,m,ans; void solve() { cin>>n>>m; f[0][0][0]=1; for(int i=1; i<=n; i++) for(int j=0; j<=m; j++) for(int k=0; k<=m-j; k++) { //这一行不放棋子 f[i][j][k]=f[i-1][j][k]; //这一行放一个棋子,分两种: //在一个有棋子的列放 if(k>=1) f[i][j][k]+=f[i-1][j+1][k-1]*(j+1); //在没有棋子的列放 if(j>=1) f[i][j][k]+=f[i-1][j-1][k]*(m-j-k+1); //放两个棋子:分三种 //都放在有一个棋子的列 if(k>=2) f[i][j][k]+=f[i-1][j+2][k-2]*(((j+2)*(j+1))/2); //一个放在有棋子的列,一个放在没有棋子的列 if(k>=1) f[i][j][k]+=f[i-1][j][k-1]*j*(m-j-k+1); //都放在没有棋子的列 if(j>=2) f[i][j][k]+=f[i-1][j-2][k]*C(m-j-k+2); f[i][j][k]%=mod; } for(int i=0; i<=m; i++) for(int j=0; j<=m; j++) (ans+=f[n][i][j])%=mod; cout<<(ans+mod)%mod<<endl; } signed main() { int t=1; while(t--) solve(); return 0; }
以上是关于luogu P2051 [AHOI2009]中国象棋 dp 状态压缩+容斥的主要内容,如果未能解决你的问题,请参考以下文章
luogu P2051 [AHOI2009]中国象棋 dp 状态压缩+容斥