写在前面
之前在考试的时候,因为太菜,没有想到正解,因而打了一个 30 p t s 30pts 30pts的暴力,居然没有T。
Solution
30 p t s 30pts 30pts做法
根据乘法原理,最终答案为每个环节的方案数乘起来。
根据加法原理,一个环节的方案数为
∑ j = l r C k i + j − l j \sum_{j=l}^{r}C_{k_{i}+{j}-{l}}^{j} j=l∑rCki+j−lj
O ( n 2 ) O(n^{2}) O(n2) 预处理组合数,然后 O ( n m ) O(nm) O(nm)统计即可。
100 p t s 100pts 100pts做法
每个环节实际上是要求
∑ j = l r C k i + j − l j = ∑ j = l r C l − k i j \sum_{j=l}^{r}C_{k_{i}+{j}-{l}}^{j}=\sum_{j=l}^{r}C_{l-k_{i}}^{j} j=l∑rCki+j−lj=j=l∑rCl−kij
而根据组合数的恒等式,有:
∑ j = l r C l − k i j = C r + 1 l − k i + 1 − C l l − k i + 1 \sum_{j=l}^{r}C_{l-k_{i}}^{j}=C^{l-{k_{i}}+1}_{r+1}-C^{l-{k_{i}}+1}_{l} j=l∑rCl−kij=Cr+1l−ki+1−Cll−ki+1
那么我们就可以直接将阶乘
O
(
N
)
O(N)
O(N)处理出来,再求逆元,这样就可以做到
O
(
M
)
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;
}