HDU6333 Problem B. Harvest of Apples 莫队算法+乘法逆元

HDU6333 Problem B. Harvest of Apples

莫队算法 求(0,n)~(m,n)组合数之和

#include <bits/stdc++.h>
using namespace std;
const int MAX=1e5+5;
const int BLOCK=(int)sqrt(1e5);
const long long MOD=1e9+7;
long long fact[MAX],inv[MAX];
struct ask
{
    int n,m,id,block;
    long long ans;
}a[MAX];
bool cmp1(ask b,ask c)
{
    return b.block==c.block?b.m<c.m:b.block<c.block;
}
bool cmp2(ask b,ask c)
{
    return b.id<c.id;
}
long long inv_(long long a,long long m)
{
    if(a==1) return 1;
    return inv_(m%a,m)*(m-m/a)%m;
}
void init()
{
    fact[0]=1;inv[0]=1;
    for(int i=1;i<MAX;i++)
    {
        fact[i]=(fact[i-1]*i)%MOD;
        inv[i]=inv_(fact[i],MOD);
    }
}
int main()
{
    int t;
    init();
    scanf("%d",&t);
    for(int k=0;k<t;k++)
    {
        scanf("%d%d",&a[k].n,&a[k].m);
        a[k].id=k;
        a[k].block=a[k].n/BLOCK;
    }
    sort(a,a+t,cmp1);
    long long sum=1;
    for(int i=1,k=a[0].n;i<=a[0].m;i++)
        sum+=fact[k]*inv[i]%MOD*inv[k-i]%MOD;
    a[0].ans=sum;
    int l=a[0].n,r=a[0].m,L,R;
    for(int i=1;i<t;i++)
    {
        L=a[i].n,R=a[i].m;
        while(L>l)
        {
            sum=(2*sum-fact[l]*inv[r]%MOD*inv[l-r]%MOD+MOD)%MOD;
            l++;
        }
        while(L<l)
        {
            sum=(sum+fact[l-1]*inv[r]%MOD*inv[l-1-r]%MOD)%MOD*inv[2]%MOD;
            l--;
        }
        while(R>r)
        {
            sum=(sum+fact[l]*inv[r+1]%MOD*inv[l-r-1]%MOD)%MOD;
            r++;
        }
        while(R<r)
        {
            sum=(sum-fact[l]*inv[r]%MOD*inv[l-r]%MOD+MOD)%MOD;
            r--;
        }
        a[i].ans=sum;
    }
    sort(a,a+t,cmp2);
    for(int i=0;i<t;i++) printf("%I64d\n",a[i].ans);
    return 0;
}
/*
S(n,m)=S(n,m-1)+(n,m)
S(n,m)=2S(n-1,m)-(n-1,m)
(n,m)=m==0?1:n!/m!/(n-m)!
*/

猜你喜欢

转载自blog.csdn.net/Nrtostp/article/details/81356036
今日推荐