题目描述:
给出T组n和m(1<=T<=1e5, 1<=m<=n<=1e5)。
求
题目分析:
记:
通过杨辉三角得出:
==
==
所以只需要求出1e5以内的全部组合数就可以进行任意移动了,组合数模板:
const int N = 1e7; //复杂度O(n)
const ll mod = 1e9 + 7;
int F[N], Finv[N], inv[N];//F是阶乘,Finv是阶乘的逆元
//X 关于 mod 的逆元为 x^(mod - 2);
void init(){
F[0] = Finv[0] = inv[1] = 1;
for (register int i = 2; i < N; i++)
inv[i] = (mod - mod / i) * 1ll * inv[mod % i] % mod;
for (register int i = 1; i < N; i++){
F[i] = F[i - 1] * 1ll * i % mod;
Finv[i] = Finv[i - 1] * 1ll * inv[i] % mod;
}
}
int comb(int n, int m){///comb(n, m)就是C(n, m)
if (m < 0 || m > n) return 0;
return F[n] * 1ll * Finv[n - m] % mod * Finv[m] % mod;
}
AC代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int INF=0x3f3f3f3f;
const int N = 1e5+7; //复杂度O(n)
const ll mod = 1e9 + 7;
int F[N], Finv[N], inv[N];
void init(){
F[0] = Finv[0] = inv[1] = 1;
for (register int i = 2; i < N; i++)
inv[i] = (mod - mod / i) * 1ll * inv[mod % i] % mod;
for (register int i = 1; i < N; i++){
F[i] = F[i - 1] * 1ll * i % mod;
Finv[i] = Finv[i - 1] * 1ll * inv[i] % mod;
}
}
int comb(int n, int m){///comb(n, m)就是C(n, m)
if (m < 0 || m > n) return 0;
return F[n] * 1ll * Finv[n - m] % mod * Finv[m] % mod;
}
inline int read(){//读入整数
int k = 0, f = 1; char c = getchar();
while (c<'0' || c>'9')c == '-' && (f = -1), c = getchar();
while ('0' <= c&&c <= '9')k = k * 10 + c - '0', c = getchar();
return k*f;
}
struct query{
int l,r,id,ans;
}q[100005];
int m;
bool cmp1(query a,query b){
if(a.l/317==b.l/317)
return a.r<b.r;
else return a.l/317<b.l/317;
}
bool cmp2(query a,query b){
return a.id<b.id;
}
void work(){
int L=1,R=0,tmp;
ll S=1;
for(int i=0;i<m;i++){
while(q[i].r<R){
tmp=comb(L,R);
S=(S-tmp+mod)%mod;
R--;
}
while(q[i].r>R){//之前以为注释部分不加进行移动会出错,其实能AC
// if(L==R){
// tmp=comb(L,R);
// S=(2*S-tmp+mod)%mod;
// L++;
// }
R++;
tmp=comb(L,R);
S=(S+tmp)%mod;
}
while(q[i].l<L){
// if(L==R){
// tmp=comb(L,R);
// S=(S-tmp+mod)%mod;
// R--;
// }
L--;
tmp=comb(L,R);
S=((S+tmp)*inv[2])%mod;
}
while(q[i].l>L){
tmp=comb(L,R);
S=(2*S-tmp+mod)%mod;
L++;
}
q[i].ans=S;
}
}
int main(){
init();
m=read();
for(int i=0;i<m;i++)
q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(q,q+m,cmp1);
work();
sort(q,q+m,cmp2);
for(int i=0;i<m;i++){
printf("%d\n",q[i].ans);
}
return 0;
}