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

BZOJ 4559 [LNOI2016 Day1]

时间:2018-01-06 22:08:20      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:main   names   body   pow   online   turn   c++   style   lin   

技术分享图片

SOL::我们有以下dp 

不难想到记f[i][j]表示统计到第i门课,此时j个人被碾压的方案数。 

 f[i][j] = f[i-1][k] * C[k][j] * C[n-k-1][n-rank[i]-j] * P[i] (k >= j) 

P[i]=j=1 to U[i])j^(nrank[i])(U[i]j)^(rank[i]1)

观察一波局势,这是一个N次多项式 我们插值就好。

我们可以发现P[i]是可以提出来最后乘。

我们来观察一波局势。

讲一波拉格朗日差值:

举个栗子:

一个三次多项式,已知(x0,y0),(x1,y1),(x2,y2),(x3,y3)

技术分享图片

通式:

技术分享图片     ,           技术分享图片 

Ln(x)所求的公式。

#pragma optimize("-O2")
#include<bits/stdc++.h>
#define sight(c) (‘0‘<=c&&c<=‘9‘)
#define mo 1000000007
#define C(a,b) (fac[a]*ni[b]%mo*ni[(a)-(b)]%mo)
#define N 107
inline void read(int &x){
    static char c;
    for (c=getchar();!sight(c);c=getchar());
    for (x=0;sight(c);c=getchar()) x=x*10+c-48;
}
#define LL long long
LL fac[N],ni[N],f[N][N];
int n,m,k,u[N],r[N];
LL qsm(LL x,LL y){
    LL an=1;
    while (y) {
        if (y&1) (an*=x)%=mo;
        y>>=1,(x*=x)%=mo;
    } return an;
 
}
inline void up(LL &x,LL y){
    x+=y; if (x>=mo) x%=mo; if (x<0) x=x%mo+mo;
}
LL answ=0;
LL t,S,sum,niv;
inline LL P(int m,int deg){
    answ=0;
    if (m<=n+1) {
        for (int i=1;i<=m;i++) 
          (answ+=qsm(i,deg)*qsm(m-i,n-deg-1)%mo)%=mo;
        return answ;
    }
    sum=niv=1;S=0;
    for (int i=1;i<=n+1;i++) sum=sum*(m-i)%mo;
    for (int i=2;i<=n+1;i++) niv=niv*(mo-i+1)%mo;
    for (int i=1;i<=n+1;i++) {
        t=sum*qsm(m-i,mo-2)%mo;
        S=(S+qsm(m-i,n-deg-1)*qsm(i,deg)%mo)%mo;
        answ=(answ+t*S%mo*qsm(niv,mo-2)%mo)%mo;
        niv=niv*i%mo*qsm(mo-n+i-1,mo-2)%mo;
    }
    return answ;
}
using namespace std;
int main () {
    read(n); read(m); read(k);
    for (int i=1;i<=m;i++) read(u[i]);
    for (int i=1;i<=m;i++) read(r[i]),r[i]=n-r[i];
    fac[0]=1; 
    for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mo;
    ni[n]=qsm(fac[n],mo-2);
    f[0][n-1]=1;
    for (int i=n;i;i--) ni[i-1]=ni[i]*i%mo;
    for (int i=1;i<=m;i++)
     for (int j=0;j< n;j++)
      for (int t=0;t<=min(j,r[i]);t++)
       if (n-j-1>=r[i]-t)
        up(f[i][t],f[i-1][j]*C(j,t)%mo*C(n-j-1,r[i]-t));
    LL ans=f[m][k];
    for (int i=1;i<=m;i++) 
      ans=ans*P(u[i],r[i])%mo;
    printf("%lld\n",ans); return 0;
}

 

BZOJ 4559 [LNOI2016 Day1]

标签:main   names   body   pow   online   turn   c++   style   lin   

原文地址:https://www.cnblogs.com/rrsb/p/8215313.html

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