HDU 6333 Problem B. Harvest of Apples [莫队]

题意

给你n个苹果,求从中取出最多m个苹果的方案数。

题解

根据题面,也就是求 S(n,m)=ΣC(n,i)(0<=i<=m) S ( n , m ) = Σ C ( n , i ) ( 0 <= i <= m )
可以简单推出S(n,m)=S(n,m-1)+C(n,m),S(n,m)=2*S(n-1,m)-C(n-1,m),这样就可以用莫队了,转移时O(1)的,总复杂度为O(T*sqrt(maxn))

AC代码

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#define N 100005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll a[N],pos[N],f[N],inv[N],len;
struct node
{
    ll l,r,id;
    node(){}
    node(ll l,ll r,ll id)
    {
        this->l=r;
        this->r=r;
        this->id=id;
    }
}q[N];
ll ansa[N];
bool cmp(node a,node b)
{
    return pos[a.l]<pos[b.l]||pos[a.l]==pos[b.l]&&a.r<b.r;
}
ll qmi(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b%2)ans=ans*a%mod;
        a=a*a%mod;
        b/=2;
    }
    return ans;
}
ll C(ll n,ll m)
{
    return f[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
    ll n=100000,m,INV=(mod+1)/2;
    f[0]=1;
    for(ll i=1;i<=n;i++)
        f[i]=(f[i-1]*i)%mod;
    for(ll i=0;i<=n;i++)
        inv[i]=qmi(f[i],mod-2);
    scanf("%lld",&m);
    len=(ll)sqrt((double)n+0.1);
    for(ll i=1;i<=n;i++)
        pos[i]=(i-1)/len+1;
    for(ll i=0;i<m;i++)
    {
        scanf("%lld%lld",&q[i].r,&q[i].l);
        q[i].id=i;
    }
    sort(q,q+m,cmp);
    ll ans=1;
    ll l=0,r=1;
    for(ll i=0;i<m;i++)
    {
        if(r<q[i].r)
        {
            for(;r<q[i].r;r++)
                ans=(2*ans-C(r,l)+mod)%mod;
        }
        if(q[i].l<l)
        {
            for(;l>q[i].l;l--)
                ans=(ans-C(r,l)+mod)%mod;
        }
        if(r>q[i].r)
        {
            for(r=r-1;r>=q[i].r;r--)
                ans=(ans+C(r,l))*INV%mod;
            r++;
        }
        if(q[i].l>l)
        {
            for(l=l+1;l<=q[i].l;l++)
                ans=(ans+C(r,l))%mod;
            l--;
        }
        ansa[q[i].id]=ans;
    }
    for(ll i=0;i<m;i++)
        printf("%lld\n",ansa[i]);

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值