【Luogu】P2490黑白棋(博弈DP)

  题目链接

  题解链接

  

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cctype>
#define mod 1000000007
#define maxn 10020
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

long long mul[maxn];
long long inv[maxn];
long long f[21][maxn];

inline long long Pow(long long a,long long b){
    long long ret=1;
    while(b){
        if(b&1)    ret=ret*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ret;
}

inline long long C(long long n,long long m){
    return (mul[n]*inv[m]%mod)*inv[n-m]%mod;
}

int main(){
    int n=read(),e=read()>>1,w=read();    mul[0]=inv[0]=1;
    for(int i=1;i<=n;++i){
        mul[i]=mul[i-1]*i%mod;
        inv[i]=Pow(mul[i],mod-2);
    }
    f[0][0]=1;
    for(int i=0;i<=14;++i){
        for(int j=0;j<=n-(e<<1);++j){
            //printf("%d %d\n",i,j);
            for(int k=0;k*(w+1)<=e&&j+k*(w+1)*(1<<i)<=n-(e<<1);++k){
                long long &now=f[i+1][j+k*(w+1)*(1<<i)];
                now=(now+f[i][j]*C(e,k*(w+1)))%mod;
            }
        }
    }
    long long ans=0;
    for(int i=0;i<=n-(e<<1);++i)    ans=(ans+f[14][i]*C(n-i-e,e))%mod;
    printf("%lld\n",(C(n,e<<1)-ans+mod)%mod);
    return 0;
}

 

posted @ 2018-05-02 07:59  Konoset  阅读(261)  评论(0编辑  收藏  举报