Problem B. Harvest of Apples
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2643 Accepted Submission(s): 1028
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
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int MAX = 1e5 + 5;
const int block = (int)sqrt(1e5);
const LL mod = 1e9 + 7;
LL fac[MAX],inv[MAX];
typedef struct Node
{
int n,m,id,block;
long long ans;
}Node;
Node node[MAX];
//按块排序,块内按r排序
bool cmp1(const Node &b,const Node &c)
{
if(b.block == c.block){
return b.m < c.m;
}
else{
return b.block < c.block;
}
}
bool cmp2(const Node &b,const Node &c)
{
return b.id < c.id;
}
LL quick_mod(LL n,LL m)
{
LL sum = 1;
LL x = n;
while(m)
{
if(m & 1)
sum= (sum * x) % mod;
m >>= 1;
x = (x * x) % mod;
}
return sum;
}
void init()
{
fac[0]=1;inv[0]=1;
for(int i = 1;i < MAX;i++)
{
//求阶乘
fac[i] = (fac[i-1] * i) % mod;
//求阶乘的逆元
inv[i] = quick_mod(fac[i], mod - 2) % mod;
}
}
int main()
{
int t;
init();
scanf("%d",&t);
for(int i = 0;i < t;++i)
{
scanf("%d %d",&node[i].n,&node[i].m);
node[i].id = i;
node[i].block = node[i].n / block;
}
sort(node,node + t,cmp1);
LL sum = 1;
for(int i = 1,k = node[0].n;i <= node[0].m;++i)
{
sum = (sum + fac[k] * inv[i] % mod * inv[k - i] % mod) % mod;
}
node[0].ans = sum;
int l = node[0].n,r = node[0].m;
int L,R;
for(int i = 1;i < t;++i)
{
L = node[i].n;
R = node[i].m;
while(L > l){
sum = (2 * sum - fac[l] * inv[r] % mod * inv[l - r] % mod + mod) % mod;
l++;
}
while(L < l){
sum = (sum + fac[l - 1] * inv[r] % mod * inv[l - 1 - r] % mod) % mod * inv[2] % mod;
l--;
}
while(R > r){
sum = (sum + fac[l] * inv[r + 1] % mod * inv[l - r - 1] % mod) % mod;
r++;
}
while(R < r)
{
sum = (sum - fac[l] * inv[r] % mod * inv[l - r] % mod + mod) % mod;
r--;
}
node[i].ans = sum;
}
sort(node,node + t,cmp2);
for(int i = 0;i < t;++i)
{
printf("%lld\n",node[i].ans);
}
return 0;
}
莫对算法讲解:http://www.mamicode.com/info-detail-2240755.html
https://blog.csdn.net/thinfatty/article/details/72581276
https://www.cnblogs.com/CsOH/p/5904430.html