1. 程式人生 > >NOIP提高模擬-20181016-T1-膜法

NOIP提高模擬-20181016-T1-膜法

寫在前面

之前在考試的時候,因為太菜,沒有想到正解,因而打了一個30pts30pts的暴力,居然沒有T。

Solution

30pts30pts做法

根據乘法原理,最終答案為每個環節的方案數乘起來。

根據加法原理,一個環節的方案數為

j=lrCki+jlj \sum_{j=l}^{r}C_{k_{i}+{j}-{l}}^{j}

O(n2)O(n^{2}) 預處理組合數,然後 O(nm)O(nm)統計即可。

100pts100pts做法

每個環節實際上是要求

j=lrCki+jlj=j=lrClkij \sum_{j=l}^{r}C_{k_{i}+{j}-{l}}^{j}=\sum_{j=l}^{r}C_{l-k_{i}}^{j}

而根據組合數的恆等式,有:

j=lrClkij=Cr+1lki+1Cllki+1 \sum_{j=l}^{r}C_{l-k_{i}}^{j}=C^{l-{k_{i}}+1}_{r+1}-C^{l-{k_{i}}+1}_{l}

那麼我們就可以直接將階乘O(N)O(N)處理出來,再求逆元,這樣就可以做到O(M)O(M)的統計。 Talk is Cheap, Show You the Code:

#include<bits/stdc++.h>
using namespace std; const int mod=1e9+7; int read(){ int sum=0,neg=1; char c=getchar(); while(c>'9'||c<'0'&&c!='-') c=getchar(); if(c=='-') neg=-1,c=getchar(); while(c>='0'&&c<='9') sum=(sum<<1)+(sum<<3)+c-'0',c=getchar(); return sum*neg; } /* 30pts long long C[2005][2005]; int n,m; void getC(){ for(int i=0;i<=n;i++) C[i][0]=C[i][i]=1; for(int i=2;i<=n;i++) for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]%mod+C[i-1][j]%mod)%mod; } int main(){ freopen("m.in","r",stdin); freopen("m.out","w",stdout); n=read(),m=read(); long long ans=1; getC(); for(int i=1;i<=m;i++){ int l,r,k; long long tmp=0; l=read(),r=read(),k=read(); for(int j=1;j<=r-l+1;j++) tmp=(tmp%mod+C[l+j-1][k+j-1]%mod)%mod; ans=(ans%mod*tmp%mod)%mod; } printf("%lld\n",ans); return 0; } */
const int N=1e5+10; int n,m; int fac[N],ifac[N]; int mul(int x,int y){ return (long long)x*y%mod; } int power(int a,int b,int ret=1){//快速冪--運用費馬小定理 for(;b;b>>=1,a=mul(a,a)) if(b&1) ret=mul(ret,a); return ret; } int calcinv(int x){//求逆元 return power(x,mod-2); } int C(int a,int b){ return (a<b)?0:mul(fac[a],mul(ifac[b],ifac[a-b])); } int dec(int x,int y){ return x-y<0?x-y+mod:x-y; } int main(){ n=read();m=read(); fac[0]=1; for(int i=1;i<=n+1;i++) fac[i]=mul(fac[i-1],i); ifac[n+1]=calcinv(fac[n+1]); for(int i=n;i>=0;i--) ifac[i]=mul(ifac[i+1],i+1); int ans=1; for(int i=1;i<=m;i++){ int l=read(),r=read(),k=read(); ans=mul(ans,dec(C(r+1,l-k+1),C(l,l-k+1))); } printf("%d\n",ans); return 0; }