HDU 6333&&18多校4B Harvest of Apples 【分块+数学】

 

HDU6333      
 

Problem B. Harvest of Apples

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 454    Accepted Submission(s): 149


 

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≤mn≤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

 


 
 

 

分析:开始想啦很久,没思路。然后队友突然说可以用离线,突然想到,然后推啦一下\sum_ {i=1}^{m}C(n,i)\sum _{i=1}^{m}C(n+1,m)的O(1)递推关系。

\sum_{i=1}^mC(n+1,m)=(2*\sum_{i=1}^mC(n,m))-C(n,m)

离线排个序看能不能快速求出,想到离散化m,感觉时间复杂度太大。然后突然想到可以分块,分200块,复杂度递推100*n.计算排序好的每个值,由于每个块大小是1000,可以通过O(500)的时间求出答案。时间复杂度O(500T+500n)。

昨天感觉能过就写啦,没多想,还有分块也不是我负责的方面,其实分\sqrt(N/2)块能达到最有效果。时间复杂度理论上能降低一半。

代码


#include
using namespace std;
typedef long long LL;
const int N=1e5;
const int ND=500;
const LL MOD=1e9+7;
const LL ny=500000004;
LL fac[N+10],inv[N+10],ans[N+10];
struct node
{
    int x,y,ind;
    bool operator<(const node& c)const
    {
        if(x==c.x)
            return y>=1;
    }
    return ret;
}
void init(int n)
{
    fac[0]=fac[1]=1;
    inv[0]=inv[1]=1;
    for(int i=2;i<=n;i++)
        fac[i]=fac[i-1]*i%MOD;
    inv[n]=pod(fac[n],MOD-2,MOD);
    for(int i=n;i>1;i--)
        inv[i-1]=inv[i]*i%MOD;
}
LL c(int n,int m)
{
    return fac[n]*inv[m]%MOD*inv[n-m]%MOD;
}
int main()
{

    init(N);
    int T;
    scanf("%d",&T);
    for(int i=1;i<=T;i++)scanf("%d%d",&a[i].x,&a[i].y),a[i].ind=i;
    sort(a+1,a+T+1);
    int x,y,ii,m=1,k;
    for(int i=1;i<=N;i++)
    {
        k=0;
        for(int j=0;j

 

 

你可能感兴趣的:(【数学】)