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<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);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_25576697/article/details/81357417
今日推荐