码迷,mamicode.com
首页 > 其他好文 > 详细

[2016北京集训测试赛17]crash的游戏-[组合数+斯特林数+拉格朗日插值]

时间:2018-09-30 21:52:01      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:博客   type   const   namespace   测试   memset   http   article   图片   

Description

技术分享图片

Solution

核心思想是把组合数当成一个奇怪的多项式,然后拉格朗日插值。。;哦对了,还要用到第二类斯特林数(就是把若干个球放到若干个盒子)的一个公式:

$x^{n}=\sum _{i=0}^{n}C(n,i)*i!*S(i,x)$

围观大佬博客(qaq公式太难打了)

Code

 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=310;
ll fac[N],finv[N],inv[N],S[N][N],inv2;
int n,m,k;
ll C(int x,int y){return x<0||y<0||x-y<0?0:fac[x]*finv[y]%mod*finv[x-y]%mod;}
ll ksm(ll x,int k){ll re=1;while (k){if (k&1) re=re*x%mod;k>>=1;x=x*x%mod;}return re;}
 
ll a[N];
void geta(int k)
{
    memset(a,0,sizeof(a));
    a[0]=1;
    for (int i=0;i<k;a[0]=0,i++) 
        for (int j=i+1;j;j--) 
            a[j]=(a[j-1]-i*a[j]%mod+mod)%mod;
    for (int i=0;i<=k;i++) a[i]=a[i]*finv[k]%mod;
}
 
ll bin[N],pnm[N];
void pre(int k)
{
    pnm[0]=1;for (int i=1;i<=k;i++) pnm[i]=pnm[i-1]*(n+m)%mod;
    bin[0]=1;for (int i=1;i<=k;i++) bin[i]=bin[i-1]*(mod-2)%mod; 
}
ll f[N];
ll ans;
int main()
{
    inv2=ksm(2,mod-2);
    inv[0]=inv[1]=fac[0]=fac[1]=finv[0]=finv[1]=1;
     
    for (int i=2;i<=300;i++) fac[i]=fac[i-1]*i%mod,inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    for (int i=2;i<=300;i++) finv[i]=finv[i-1]*inv[i]%mod;
     
    S[0][0]=1;
    for (int i=1;i<=300;i++) for (int j=1;j<=i;j++) 
    S[i][j]=(S[i-1][j-1]+S[i-1][j]*j)%mod;
     
    int T;
    scanf("%d",&T); 
    while (T--)
    {
        scanf("%d%d%d",&n,&m,&k);
        ans=0;
        pre(k);geta(k);
        ll cnt=ksm(2,m);
        for (int i=0;i<=k;i++)
        {
            ll s=0,Cmj=1,m_j=cnt;
            for (int j=0;j<=i;j++)
            {
                s+=S[i][j]*fac[j]%mod*Cmj%mod*m_j%mod;
                Cmj=Cmj*(m-j)%mod*inv[j+1]%mod;
                m_j=m_j*inv2%mod;           
            }
            f[i]=s%mod;
        }
        for (int i=0;i<=k;i++)
        {
            ll s=0;
            for (int t=0;t<=i;t++) s+=C(i,t)*bin[i-t]%mod*pnm[t]%mod*f[i-t]%mod;
            ans+=s%mod*a[i]%mod;
        }
        printf("%lld\n",ans%mod);
    }
}

 

[2016北京集训测试赛17]crash的游戏-[组合数+斯特林数+拉格朗日插值]

标签:博客   type   const   namespace   测试   memset   http   article   图片   

原文地址:https://www.cnblogs.com/coco-night/p/9733368.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!