zoukankan      html  css  js  c++  java
  • hdu4779 组合计数+dp

    提交

    题意:给了n*m的网格,然后有p个重型的防御塔,能承受1次攻击,q个轻型防御塔不能接受任何攻击,然后每个防御搭会攻击他所在的行和所在的列,最后求在这个网格上放至少一个防御塔的方案数,

    我们枚举 选取多少个重型防御塔然后这个重型防御塔有多少是两个在一行,和两个在一列 O(P^3)的效率

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <string.h>
    #include <vector>
    using namespace std;
    typedef long long LL;
    const LL MOD=1000000007;
    const int maxn=202;
    LL C[maxn][maxn];//组合数
    LL light[maxn][maxn][maxn];// light[i][j][k]k栈轻量级的防御塔放在i行j列的矩阵的方案数
    LL heavy[maxn];// haeavy[i] 表示有i个两个同一行的重量级的方案数
    LL Nt[maxn];//N! n阶乘
    void init()
    {
        Nt[0]=1;
        for(LL i=1; i<=200; i++)
            Nt[i]=(Nt[i-1]*i)%MOD;
        memset(C,0,sizeof(C));
        C[0][0]=1;
        for(int i=1; i<=200; i++)
        {
            C[i][0]=1;
            for(int j=1; j<=i; j++)
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
        }
        for(int i=1; i<=200; i++)
            for(int j=1; j<=200; j++)
            {
                 int kM=min(i,j);
                 light[ i ][ j ][ 0 ] = 1;
                 for(int k=1; k<=kM; k++)
                 {
                    light[ i ][ j ][ k ]=( ( (C[ i ][ k ]*C[ j ][ k ])%MOD )*Nt[k])%MOD;
                 }
            }
        for(int i=1; i<=200; i++)
            for(int j=1; j<=200; j++)
            {
                 int kM=min(i,j);
                 for(int k=1; k<=kM; k++)
                    light[i][j][k]=(light[i][j][k-1]+light[i][j][k])%MOD;
            }
        heavy[0]=1;
        for(int i=1; i<=100; i++)
        {
            LL ans=1;
            for(int j=i*2; j>2; j-=2 )
            {
                ans=(C[j][2]*ans)%MOD;
            }
            heavy[i]=ans;
        }
    }
    
    int main()
    {
        init();
        int N,M,P,Q;
        int cas;
        scanf("%d",&cas);
        for(int cc=1; cc<=cas; cc++)
        {
            scanf("%d%d%d%d",&N,&M,&P,&Q);
             LL ans=0;
             for(int k=1; k<=P; k++)
                for(int i=0; i<=k; i+=2)
                  for(int j=0; j+i<=k; j+=2)
                  {
                     int LN=N-i/2-j;
                     int LM=M-j/2-i;
                     if(min(LN,LM)<k-(i+j) )continue;
                     LN=N,LM=M;
                     LL d=1;
                     d=( ( ( C[LN][i/2]*C[LM][i] )%MOD )*heavy[i/2])%MOD;
                     LN-=i/2; LM-=i;
                     d=( d*( ( ( ( C[LN][j] * C[LM][j/2] )%MOD ) * heavy[j/2] )%MOD ) )%MOD;
                     LN-=j;
                     LM-=j/2;
                     int lest=k-(i+j);
                     d= ( ( ( d*( ( C[LN][lest]*C[LM][lest] )%MOD ))%MOD)*Nt[lest] )%MOD;
                     LN-=lest;LM-=lest;
                     if(LN>0&&LM>0)
                     {
                         int ge=min(min(LN,LM),Q);
                         d=(d*(light[LN][LM][ge]))%MOD;
                     }
                     ans=(ans+d)%MOD;
                  }
            if(Q>0)
            {
                int ge=min(min(N,M),Q);
                ans=(ans+light[N][M][ge])%MOD;
                ans=(ans-1+MOD)%MOD;
            }
            printf("%I64d
    ",ans%MOD);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    百斯特
    C++
    转载
    转载+整理
    转载
    转载
    转载
    C++
    转载
    CodeForces
  • 原文地址:https://www.cnblogs.com/Opaser/p/4949220.html
Copyright © 2011-2022 走看看