HDU6143 Killer Names 【數學+組合】

鏈接


f(n,m)=n,使m
f(n,m)=mnm1i=1[Cimf(n,mi)]
name1使i,name2使j
f(n,i)f(n,j)CimCjmi
i,j ans=i>0,j>0,i+j>0[f(n,i)f(n,j)CimCjmi]

#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))

using namespace std;

const int inf=1e9+7;
const int N = 2000 + 5;

ll c[N][N];

ll C(ll n,ll m){
    if(n<m){
        return 0;
    }
    if(n==m||m==0){
        return 1;
    }
    if(c[n][m]!=-1){
        return c[n][m];
    }
    return (c[n][m]=(C(n-1,m-1)+C(n-1,m))%inf);
}

ll qPow(ll a,ll n){
    ll ans=1;
    ll t=a%inf;
    while(n){
        if(n&1){
            ans=(ans*t)%inf;
        }
        t=(t*t)%inf;
        n>>=1;
    }
    return ans;
}

ll f[N];

ll ff(int n,int m){
    f[1]=1;
    for(int i=2;i<=m;++i){
        f[i]=qPow(i,n);
        for(int j=1;j<i;++j){
            f[i]=(f[i]-C(i,j)*f[i-j])%inf;
        }
    }
    return f[m];
}

ll slove(int n,int m){
    ff(n,m);
    ll ans=0;
    for(int a=0;a<=m;++a){
        for(int b=0;a+b<=m;++b){
            if(a+b==0){
                continue;
            }
            ll t=(C(m,a)*f[a])%inf;
            t=(t*C(m-a,b))%inf;
            t=(t*f[b])%inf;
            ans=(ans+t)%inf;
        }
    }
    return (ans+inf)%inf;
}

int main()
{
    //freopen("/home/lu/code/r.txt","r",stdin);
    //freopen("/home/lu/code/w.txt","w",stdout);
    int T;
    scanf("%d",&T);
    MEM(c,-1);
    while(T--){
        int n,m;
        scanf("%d%d",&n,&m);
        printf("%lld\n",slove(n,m));
    }
    return 0;
}
發佈了292 篇原創文章 · 獲贊 82 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章