[51Nod1371]填数字(DP)

版权声明:转载需要注明哦QwQ,地址:http://blog.csdn.net/effervescence。 https://blog.csdn.net/Effervescence/article/details/82289980

  题目传送门

分析

  考虑DP, f [ i ] [ j ] [ k ] 表示前 i 行里有 j 列可以填 1 ,有 k 列可以填 2 ,然后我们有 7 种转移:
(1)什么都不填,有 1 种方法,即 f [ i + 1 ] [ j ] [ k + 1 ] + = f [ i ] [ j ] [ k ]
(2)在前面几列中某一列填 2 ,有 k + 1 种方法,即 f [ i + 1 ] [ j ] [ k ] + = ( k + 1 ) f [ i ] [ j ] [ k ]
(3)在前面几列中某一列原来可以填 2 的列上填 1 ,有 k + 1 种方法,即 f [ i + 1 ] [ j + 1 ] [ k ] + = ( k + 1 ) f [ i ] [ j ] [ k ]
(4)在前面几列中某一列原来可以填 1 的列上填 1 ,有 j 种方法,即 f [ i + 1 ] [ j 1 ] [ k ] + = j f [ i ] [ j ] [ k ] ( j > 0 )
(5)在前面几列中某两列原来可以填 2 的列上填 1 ,有 ( k + 1 ) k / 2 种方法,即 f [ i + 1 ] [ j + 2 ] [ k 1 ] + = ( k ( k + 1 ) / 2 ) f [ i ] [ j ] [ k ] ( k > 0 )
(6)在前面几列中某两列原来可以填 1 的列上填 1 ,有 j ( j 1 ) / 2 种方法,即 f [ i + 1 ] [ j 2 ] [ k + 1 ] + = ( j ( j 1 ) / 2 ) f [ i ] [ j ] [ k ] ( j > 1 )
(7)分别在一列原来可以填 2 的列和原来可以填 1 的列上填 1 ,有 j ( k + 1 ) 种方法,即 f [ i + 1 ] [ j ] [ k ] + = ( j ( k + 1 ) ) f [ i ] [ j ] [ k ]
  最后答案就是 i = 0 n j = 0 n f [ n ] [ i ] [ j ] ( i + j <= n )

Code

#include<bits/stdc++.h>
using namespace std;
const int mod=1e8+7;
namespace {
    inline int Half(const int &x) {
        return x&1?x+mod>>1:x>>1;
    }
    inline int Add(const int &x,const int &y) {
        int res=x+y;
        return res>=mod?res-mod:res;
    }
    inline int Sub(const int &x,const int &y) {
        int res=x-y;
        return res<0?res+mod:res;
    }
    inline int Mul(const int &x,const int &y) {
        return 1ll*x*y%mod;
    }
    inline int C_2(const int &x) {
        return Half(Mul(x,x-1));
    }
}
int f[205][205][205],n;
int main() {
    cin>>n;
    f[0][0][0]=1;
    for(int i=0;i<n;++i)
        for(int j=0;j<=i;++j)
            for(int k=0;k<=i;++k)
                if(j+k<=i) {
                    /*Tramsform place Nothing:*/ {
                        f[i+1][j][k+1]=Add(f[i+1][j][k+1],f[i][j][k]);
                    }
                    /*Transform Place a two:*/ {
                        f[i+1][j][k]=Add(f[i+1][j][k],Mul(k+1,f[i][j][k]));
                    }
                    /*Transform Place a one in k*/ {
                        f[i+1][j+1][k]=Add(f[i+1][j+1][k],Mul(k+1,f[i][j][k]));
                    }
                    /*Tramsform Place a one in j*/ {
                        if(j)
                            f[i+1][j-1][k+1]=Add(f[i+1][j-1][k+1],Mul(j,f[i][j][k]));
                    }
                    /*Transform Place two one in j*/ {
                        if(j>1)
                            f[i+1][j-2][k+1]=Add(f[i+1][j-2][k+1],Mul((1ll*(j-1)*j/2)%mod,f[i][j][k]));
                    }
                    /*Transform Place a one in j and a one in k*/ {
                        if(j)
                            f[i+1][j][k]=Add(f[i+1][j][k],Mul(Mul(j,k+1),f[i][j][k]));
                    }
                    /*Transform Place two one in k*/ {
                        if(k)
                            f[i+1][j+2][k-1]=Add(f[i+1][j+2][k-1],Mul((1ll*(k+1)*k/2)%mod,f[i][j][k]));
                    }
                }
    int ans=0;
    for(int j=0;j<=n;++j)
        for(int k=0;k<=n;++k)
            if(j+k<=n)
                ans=Add(ans,f[n][j][k]);
    cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/Effervescence/article/details/82289980