BZOJ 4559 [LNOI2016 Day1]
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^(n−rank[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; }