hdu6333(杭電多校第四場B)分塊

Problem B. Harvest of Apples

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1463    Accepted Submission(s): 555
ios

Problem Descriptionapp

There are n apples on a tree, numbered from 1 to n.
Count the number of ways to pick at most m apples.
spa

Input.net

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).
code

Outputblog

For each test case, print an integer representing the number of ways modulo 109+7.ip

Sample Inputget

2 input

5 2 string

1000 500

Sample Output

16

924129523

 

題意:計算c(n,0),c(n,1),,,c(n,m); 

思路:分塊,將1e5分紅根號1e5塊(333)。採用逆元的方式計算出n爲333倍數的全部組合數,在處理出其前綴,另外處理處n<333的全部組合數,這樣對於n<333的狀況直接處理便可,對於n>=333狀況,分爲兩部分一部分爲333的倍數p,另外一部分爲除以333的餘數q,這樣就能夠轉換爲在這兩部份內分別處理。總時間複雜度爲O(333*T)。

參考自:https://blog.csdn.net/zstu_zy/article/details/81334302

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 1e5+10;
ll dp[335][maxn],C[335][335];
ll inv[maxn],fac[maxn],invf[maxn];
void init()
{
    inv[1]=1;  
    for (int i=2;i<maxn;i++)  
        inv[i]=((mod-mod/i)*inv[mod%i])%mod; 
    fac[0] = 1; 
    for(int i = 1;i<maxn;i++)
        fac[i] = (fac[i-1] * (ll)i)%mod;
    invf[0] = 1;
    for(int i = 1;i<maxn;i++)
        invf[i] = (invf[i-1]*inv[i])%mod;
    C[0][0] = 1;
    for(int i=1;i<335;i++)
    {
        C[i][0] = 1;
        for(int j=1;j<=i;j++)
            C[i][j] = (C[i-1][j]+C[i-1][j-1])%mod;
    }
    dp[0][0] = 1;
    for(int i=1;i*333<maxn;i++)
    {
        for(int j=0;j<=i*333;j++)
        {
            dp[i][j] = ((fac[i*333]*invf[j])%mod*invf[i*333-j])%mod;
            if(j>0)dp[i][j] = (dp[i][j] + dp[i][j-1])%mod;
        }
    }

}
int main()
{
    init();
    int t;
    int n,m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        int p = n/333,q = n%333;
        ll ans = 0;
        if(n<=333)
        {
            for(int i = 0;i <= m;i++)ans = (ans + C[n][i])%mod;
            printf("%lld\n",ans);
        }
        else
        {
            for(int i =0;i<=min(q,m);i++)
            {
                ans = (ans + (C[q][i]*dp[p][min(m-i,p*333)])%mod)%mod;
            }
            printf("%lld\n",ans);
        }
    }
}