码迷,mamicode.com
首页 > 其他好文 > 详细

luogu P2051 [AHOI2009]中国象棋 dp 状态压缩+容斥

时间:2020-07-03 14:05:54      阅读:57      评论:0      收藏:0      [点我收藏+]

标签:状态压缩   象棋   www   +=   long   sig   ble   log   air   

参考: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 状态压缩+容斥

标签:状态压缩   象棋   www   +=   long   sig   ble   log   air   

原文地址:https://www.cnblogs.com/QingyuYYYYY/p/13230038.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!