HDU - 6333 Harvest of Apples (莫队)

题目vj链接

题面:
在这里插入图片描述

题意:
给定 T T T 组查询,每次询问 C n 0 + C n 1 + C n 2 + . . . + C n m C_n^0+C_n^1+C_n^2+...+C_n^m Cn0+Cn1+Cn2+...+Cnm

题解:
我们设 S n m = C n 0 + C n 1 + C n 2 + . . . + C n m S_n^m=C_n^0+C_n^1+C_n^2+...+C_n^m Snm=Cn0+Cn1+Cn2+...+Cnm

有:
S n m = S n m − 1 + C n m S_n^m=S_n^{m-1}+C_n^m Snm=Snm1+Cnm

S n m = 2 S n − 1 m − C n − 1 m S_n^m=2S_{n-1}^m-C_{n-1}^m Snm=2Sn1mCn1m

那么:
l − > l − 1 , S l − 1 r = ( S l r + C l − 1 r ) ∗ i n v 2 l->l-1,S_{l-1}^r=(S_l^r+C_{l-1}^r)*inv2 l>l1Sl1r=(Slr+Cl1r)inv2

l − > l + 1 , S l + 1 r = 2 S l r − C l r l->l+1,S_{l+1}^r=2S_l^r-C_l^r l>l+1Sl+1r=2SlrClr

r − > r − 1 , S l r − 1 = S l r − C l r r->r-1,S_l^{r-1}=S_l^r-C_l^r r>r1Slr1=SlrClr

r − > r + 1 , S l r + 1 = S l r + C l r + 1 r->r+1,S_l^{r+1}=S_l^{r}+C_l^{r+1} r>r+1Slr+1=Slr+Clr+1

可以快速转移。
莫队即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x)  (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
#define fhead(x) for(int i=head[(x)];i;i=nt[i])
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
using namespace std;

const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=100100;
const int maxm=100100;
const int maxp=100100;
const int up=100100;

ll ans[maxn],res,inv2;
ll pos[maxn],fac[maxn],inv[maxn];
struct node
{
    ll l,r,id;
}a[maxn];

ll mypow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

void init(ll n)
{
    inv2=mypow(2,mod-2);
    ll t=sqrt(n);
    for(int i=1;i<=n;i++)
        pos[i]=(i-1)/t+1;
    fac[0]=1;
    for(ll i=1;i<=n;i++)
        fac[i]=fac[i-1]*i%mod;
    inv[n]=mypow(fac[n],mod-2);
    for(ll i=n-1;i>=0;i--)
        inv[i]=inv[i+1]*(i+1)%mod;
}


ll C(int n,int m)
{
    if(n<0||m<0||m>n) return 0;
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}

bool cmp(const node &a,const node &b)
{
    if(pos[a.l]!=pos[b.l]) return pos[a.l]<pos[b.l];
    else if(pos[a.l]&1) return a.r<b.r;
    else return a.r>b.r;
}

void addl(int l,int r)//l-->l+1
{
    res=(res*2-C(l,r)+mod)%mod;
}

void dell(int l,int r)//l-->l-1
{
    res=(res+C(l,r))*inv2%mod;
}

void addr(int l,int r)//r-->r+1
{
    res=(res+C(l,r))%mod;
}

void delr(int l,int r)//r-->r-1
{
    res=(res-C(l,r)+mod)%mod;
}


int main(void)
{
    ll n;
    init(maxn-1);

    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&a[i].l,&a[i].r),a[i].id=i;

    sort(a+1,a+n+1,cmp);

    int ql=0,qr=0;
    res=1;
    //S(0,0)=C(0,0)=1;
    /*以下也可。

        int ql=1,qr=0;
        res=1;
        S(1,0)=C(1,0)=1;

    */
    for(int i=1;i<=n;i++)
    {
        int nowl=a[i].l,nowr=a[i].r;
        while(ql<nowl) addl(ql,qr),ql++;
        while(ql>nowl) ql--,dell(ql,qr);
        while(qr<nowr) qr++,addr(ql,qr);
        while(qr>nowr) delr(ql,qr),qr--;
        ans[a[i].id]=res;
    }
    for(int i=1;i<=n;i++)
        printf("%lld\n",ans[i]);

    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值