zoukankan      html  css  js  c++  java
  • BZOJ1801:[AHOI2009]中国象棋——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1801

    https://www.luogu.org/problemnew/show/P2051

    这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。你也来和小可可一起锻炼一下思维吧!

    我思维断掉了,秉承着dp试图自己做出来。

    先想到dp方程有一维一定是处理到第几行,剩下的就是前几行的状态。

    考虑状压……emm这100的大小状压可承受不起啊。

    稍等,一列最多就两个炮啊!

    我们完全可以用一种三维进制表示出每一列有多少个炮,这是是50%的做法。

    正解延续了这个思想,显然我们只需要记住有多少列有0/1/2炮,经过奇妙的转移就能得到结果。

    (然后斜挂不可避……)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll p=9999973;
    int n,m;
    ll f[101][101][101];
    int main(){
        scanf("%d%d",&n,&m);
        f[0][0][0]=1;
        for(int i=0;i<n;i++){
        for(int j=0;j<=m;j++){
            for(int k=0;k+j<=m;k++){
            int l=m-j-k;
            f[i+1][j][k]=(f[i+1][j][k]+f[i][j][k])%p;
            if(l>0)f[i+1][j+1][k]=(f[i+1][j+1][k]+f[i][j][k]*l)%p;
            if(j>0)f[i+1][j-1][k+1]=(f[i+1][j-1][k+1]+f[i][j][k]*j)%p;
            if(l>1)f[i+1][j+2][k]=(f[i+1][j+2][k]+f[i][j][k]*l*(l-1)/2)%p;
            if(l>0&&j>0)f[i+1][j][k+1]=(f[i+1][j][k+1]+f[i][j][k]*l*j)%p;
            if(j>1)f[i+1][j-2][k+2]=(f[i+1][j-2][k+2]+f[i][j][k]*j*(j-1)/2)%p;
            }
        }
        }
        ll ans=0;
        for(int j=0;j<=m;j++){
        for(int k=0;k+j<=m;k++){
            ans=(ans+f[n][j][k])%p;
        }
        }
        printf("%lld
    ",ans);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

     +本文作者:luyouqi233。               +

     +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    python 爬虫 urllib模块 url编码处理
    python 爬虫 urllib模块 目录
    python 爬虫 urllib模块介绍
    python 爬虫 目录
    爬虫 介绍
    POJ 2533
    POJ 2531
    POJ 2524
    POJ 2505
    POJ 2521
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8497059.html
Copyright © 2011-2022 走看看