Problem B. Harvest of Apples
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3018 Accepted Submission(s): 1180
Problem Description
There are n apples on a tree, numbered from 1 to n.
Count the number of ways to pick at most m apples.Input
The first line of the input contains an integer T (1≤T≤105) denoting the number of test cases.
Each test case consists of one line with two integers n,m (1≤m≤n≤105).Output
For each test case, print an integer representing the number of ways modulo 109+7.
Sample Input
2
5 2
1000 500
Sample Output
16
924129523
Source
题意:
给你n,m两个数,问你在n个中最多取m个有多少种取法。
使用算法:
莫队 + 组合数 + 逆元
题解:
其实就是求()
这个题组合数求模时,需要用到逆元,逆元可以避免除法,将除变为乘,即当时,此时c称为a的逆元。
假设c是b的逆元 ①,根据费马小定理: 时, ② (p表示素数)
联立①②可得: 所以模(p-2)就好
然后回到这题,显而易见可以得到
根据组合数的递推公式
,
把上式的变成或者 得到:
根据红字的公式用莫队离线操作
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=b;i>=a;i--)
#define ll long long
#define int64 __int64
const ll mod = 1e9 + 7;
const ll MAXN = 1e5 + 5;
const ll MAXM = 1e9 + 5;
struct node {
int n,m,id;
} A[MAXN];
int pos[MAXN];
ll inv[MAXN],num[MAXN],ans[MAXN];
int cmp(node x,node y) {
if(pos[x.n] != pos[y.n]) {
return x.n < y.n;
}
return x.m < y.m;
}
ll quickpow(ll a,ll b) {
ll ans=1;
while(b) {
if(b&1) {
ans=(ans*a)%mod;
}
a=(a*a)%mod;
b>>=1;
}
return ans;
}
void init() {
num[1] = 1;
for(int i = 2; i < MAXN; i++) num[i] = (num[i-1] *i)%mod;
for(int i = 1; i < MAXN; i++) inv[i] = quickpow(num[i],mod -2);
}
ll C(int n, int m) {
if(n < 0 || m < 0 || m > n) return 0;
if(m == 0|| m == n) return 1;
return num[n] * inv[n - m]%mod*inv[m]%mod;
}
ll res = 1;
int main() {
init();
int t;
scanf("%d",&t);
int block = sqrt(MAXN);
rep(i,1,MAXN - 1) pos[i] = (i - 1) / block;
rep(i,1,t) {
scanf("%d%d",&A[i].n,&A[i].m);
A[i].id = i;
}
sort(A+1,A+t+1,cmp);
int N = 1,M = 0;
rep(i,1,t) {
while(N<A[i].n)res = (2*res - C(N++,M)+mod)%mod;
while(N>A[i].n) res=((res+C(--N,M))*inv[2])%mod;
while(M<A[i].m) res=(res+C(N,++M))%mod;
while(M>A[i].m) res=(res-C(N,M--)+mod)%mod;
ans[A[i].id]=res;
}
rep(i,1,t)
printf("%lld\n", ans[i]);
}