HDU 6333 莫队+组合数

Problem B. Harvest of Apples

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

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

Source

2018 Multi-University Training Contest 4

解析  不难发现S(n,m)也满足左上角加右上角(杨辉三角)  所以根据公式可以O(1)得到S(n-1,m),S(n+1,m),S(n,m-1),S(n,m+1) 可以看做区间的转移 从而套用莫队实现求解

AC代码

#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan prllf("\n");
#define debug(a,b) cout<<a<<" "<<b<<" ";
using namespace std;
typedef long long ll;
const ll maxn=1e5+10,inf=0x3f3f3f3f;
const ll mod=1e9+7;
ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}
ll fac[maxn],inv[maxn],ans[maxn];
ll chunk;
struct node
{
    ll l,r,id,chunk;
}q[maxn];
bool cmp(node a,node b)
{
    if(a.chunk!=b.chunk)
        return a.l<b.l;
    return a.r<b.r;
}
void init()
{
    fac[0]=fac[1]=1;
    inv[0]=inv[1]=1;
    for(ll i=2;i<maxn;i++)
    {
        fac[i]=fac[i-1]*i%mod;
        inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    }
    for(ll i=2;i<maxn;i++)         //不可以写成一个for inv还会用到
        inv[i]=inv[i-1]*inv[i]%mod;  //可以再开一个数组 写成一个for
}
ll C(ll x,ll y)
{
    if(y>x) return 0;
    return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
int main()
{
    init();//预处理组合数逆元 从而O(1)获得组合数 实现转移
    ll t;
    chunk=sqrt(maxn);
    scanf("%lld",&t);
    for(ll i=1;i<=t;i++)
    {
        ll n,m;
        scanf("%lld%lld",&n,&m);
        q[i]=node{n,m,i,n/chunk+1};
    }
    sort(q+1,q+1+t,cmp);
    ll l=1,r=0,res=1;
    for(ll i=1;i<=t;i++)
    {
        while(l<q[i].l)
        {
            res=(res*2%mod-C(l,r)+mod)%mod;
            l++;
        }
        while(l>q[i].l)
        {
            l--;
            res=(res+C(l,r))%mod*inv[2]%mod;
        }
        while(r>q[i].r)
        {
            res=(res-C(l,r)+mod)%mod;
            r--;
        }
        while(r<q[i].r)
        {
            r++;
            res=(res+C(l,r))%mod;
        }
        ans[q[i].id]=res;
    }
    for(ll i=1;i<=t;i++)
        printf("%lld\n",ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/stranger-/p/9414187.html

时间: 2024-08-01 20:50:11

HDU 6333 莫队+组合数的相关文章

HDU6333 莫队+组合数

题目大意: 给定n m 在n个数中最多选择m个的所有方案 #include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define LL long long const int mod=1e9+7; const int N=1e5+5; /********组合数模板*********/ LL pow_mod(LL a, LL b) { LL res = 1LL; a %= mod; while(b){ if(b &

HDU 4638 莫队算法

Group Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2483    Accepted Submission(s): 1272 Problem Description There are n men ,every man has an ID(1..n).their ID is unique. Whose ID is i and i-

HDU 4638 (莫队)

题目链接:Problem - 4638 做了两天莫队和分块,留个模板吧. 当插入r的时候,设arr[r]代表r的位置的数字,判断vis[arr[r-1]]和vis[arr[r+1]]是否访问过,如果两个都访问过,那么块的个数-1,如果有一个访问过,块的个数不变,如果都为0,块的个数+1. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm>

HDU 5145 NPY and girls (莫队分块离线)

题目地址:HDU 5145 莫队真的好神奇..这样的复杂度居然只有n*sqrt(n)... 裸的莫队分块,先离线,然后按左端点分块,按块数作为第一关键字排序,然后按r值作为第二关键字进行排序.都是从小到大,可以证明这样的复杂度只有n*sqrt(n).然后进行块之间的转移. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <

【HDU 5145】 NPY and girls(组合+莫队)

pid=5145">[HDU 5145] NPY and girls(组合+莫队) NPY and girls Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 593    Accepted Submission(s): 179 Problem Description NPY's girlfriend blew him out!H

hdu NPY and girls 莫队+逆元

NPY and girls Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description NPY's girlfriend blew him out!His honey doesn't love him any more!However, he has so many girlfriend candidates.Because there are to

hdu 5381 The sum of gcd 莫队+预处理

The sum of gcd Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description You have an array A,the length of A is nLet f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj) Input There are multiple test cases. The first line

HDU 5145 NPY and girls(莫队算法+乘法逆元)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5145 [题目大意] 给出一个数列,每次求一个区间数字的非重排列数量.答案对1e9+7取模. [题解] 我们发现每次往里加入一个新的数字或者减去一个新的数字,前后的排列数目是可以通过乘除转移的,所以自然想到用莫队算法处理.因为答案要求取模,所以在用除法的时候要计算逆元. [代码] #include <cstdio> #include <algorithm> #include <

HDU 5145 分块 莫队

给定n个数,q个询问[l,r]区间,每次询问该区间的全排列多少种. 数值都是30000规模 首先考虑计算全排列,由于有同种元素存在,相当于每次在len=r-l+1长度的空格随意放入某种元素即$\binom{len}{k_1}$,那么下种元素即为$\binom{len-k_1}{k2}$,以此类推,直至最后直接填满,那么全排列为${\frac{len!}{k_1!k_2!…k_n!}}$ 然后可以发现可以直接O(1)求得左右相邻区间的值(就是乘或除),那么考虑分块莫队. /** @Date : 2