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

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

 

题意:计算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
#include
#include
#include
#include
#include
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;i0)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);
        }
    }
}

 

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