問題を解決P2051 [[AHOI2009]中国のチェス]

トピックリンク

ソリューション[AHOI2009]中国のチェス

タイトル効果:シークで\(N- \) OK \(m個\)をガンの複数の列数はとする、実施態様その攻撃しないように基板上に配置されている\(9999973 \)モジュロ

分析:同一の行/列に互いに銃3つの銃を攻撃しないように同等がありません

検討([i]が[M_1 fを\ ] [M_2] \) 前者表す\(Iは\)に沿っ、\(M_1を\)カラムが銃を持っている、\(M_2 \) 2つの銃記載されているプログラム番号

表ブラシ方式は、思考の困難さを軽減することができます

初期条件:

\(F [1] [0] [0] = 1 \)

(\ [1] [1] [0] = M F)\

\(F [1] [2] [0] = C_m ^ 2 \)

これは、転送が大幅すなわち議論、議論分類することができる、比較的簡単である\(I + 1 \)行の数を入れ、プログラムを配置されています

  • \(1.I + 1 \)ラインプット\(0 \) A

\(F [I + 1] [M_1] [M_2] + = F [i]が[M_1] [M_2] \)

  • \(2.I + 1 \)ライン排出\(1 \) A、および(持つ空のカラムに\(0 \)列の個目)

\(F [I + 1] [M_1 + 1] [M_2] + = F [i]が[M_1] [M_2] \回(M - M_1 - M_2)\)

  • \(3.I + 1 \)ライン排出\(1 \) A、およびそこに配置された\(1 \)列の個目

\([I + 1] [M_1 - 1] F [M_2 + 1] + = F [i]が[M_1] [M_2] \回M_1 \)

  • \(4.I + 1 \)ライン放電\(2 \) A、空の列が配置されています

\(F [I + 1] [M_1 + 2] [M_2] + = F [i]が[M_1] [M_2] \回C_ {M-M_1 - M_2} ^ 2 \)

  • \(5.I + 1 \)ライン放電\(2 \)に、空の列内の1つ、\(1 \)列の個目

\(F [I + 1] [M_1] [M_2 + 1] + = F [i]が[M_1] [M_2] \回M_1 \倍(M - M_1 - M_2)\)

  • \(6.i + 1 \)ライン放電\(2 \) A、そこに配置されている\(1 \)列の個目

\([I + 1] [M_1 - 2] F [M_2 + 2] + = F [i]が[M_1] [M_2] \回C_ {M_1} ^ 2 \)

そして、違法状態を回避するために、境界条件に注意し、不法に転送

#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn = 128,mod = 9999973;
int n,m;
ll f[maxn][maxn][maxn],ans;
inline ll C2(ll x){return x * (x - 1) / 2;}
int main(){
    scanf("%d %d",&n,&m);
    f[1][0][0] = 1;
    f[1][1][0] = m;
    f[1][2][0] = C2(m);
    for(int i = 1;i < n;i++)
        for(int m1 = 0;m1 <= m;m1++)
            for(int m2 = 0;m1 + m2 <= m;m2++){
                f[i + 1][m1][m2] += f[i][m1][m2],f[i + 1][m1][m2] %= mod;
                if(m1 + 1 <= m && m1 + m2 + 1 <= m)f[i + 1][m1 + 1][m2] += f[i][m1][m2] * ll(m - m1 - m2),f[i + 1][m1 + 1][m2] %= mod;
                if(m1 >= 1 && m2 < m)f[i + 1][m1 - 1][m2 + 1] += f[i][m1][m2] * (ll)m1,f[i + 1][m1 - 1][m2 + 1] %= mod;
                if(m1 + 2 <= m && m1 + m2 + 2 <= m)f[i + 1][m1 + 2][m2] += f[i][m1][m2] * C2(m - m1 - m2),f[i + 1][m1 + 2][m2] %= mod;
                if(m2 + 1 <= m && m1 + m2 + 1 <= m)f[i + 1][m1][m2 + 1] += f[i][m1][m2] * ll(m - m1 - m2) * m1,f[i + 1][m1][m2 + 1] %= mod;
                if(m1 >= 2 && m2 + 2 <= m)f[i + 1][m1 -  2][m2 + 2] += f[i][m1][m2] * C2(m1),f[i + 1][m1 - 2][m2 + 2] %= mod;
            }
    for(int m1 = 0;m1 <= m;m1++)
        for(int m2 = 0;m1 + m2 <= m;m2++)
            ans += f[n][m1][m2],ans %= mod;
    printf("%lld\n",ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/colazcy/p/11520079.html