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

    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
    ",ans%mod);
        }
    }
  • 相关阅读:
    PCB genesis方槽加内角槽孔实现方法
    PCB genesis连孔加除毛刺孔(槽孔与槽孔)实现方法(三)
    PCB genesis连孔加除毛刺孔(圆孔与槽孔)实现方法(二)
    PCB genesis连孔加除毛刺孔(圆孔与圆孔)实现方法(一)
    为什么要用Redis而不直接用Map做缓存
    Linux 查询端口被占用命令
    HashMap 和 Hashtable 的区别
    RandomAccess是什么
    接口和抽象类的区别是什么?
    为什么 Java 中只有值传递?
  • 原文地址:https://www.cnblogs.com/coco-night/p/9733368.html
Copyright © 2011-2022 走看看