题意:求所有自己的最小公倍数的和。 该集合是  2^ai  * 3^bi

思路:线段树。 线段树中存的是  【3^b * f(b)】   f(b)表示 因子3 的最小公倍数3的部分  为 3^b的个数  那么从小到大枚举a  对于当前的  ab  ,  如果之前的b小于当前的b  那么最小公倍数就为  (2^a) *  (3^b)   个数 就为 2^x     x表示a  b 都小于当前a b的个数 。  大于的部分 就直接是  2^a   * 线段树上【b,max】的和。   求好当前更新进去,对于 【b,max】 区间 直接乘2 (表示当前这个b可选可不选) 。       b位置加上(2^x)  * (3^b) 的值即可(当前b被选为最大的b时的个数)。

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include <iostream>
#define lson i<<1
#define rson i<<1|1
#define LL long long
#define N 100050
#define MOD 1000000007
using namespace std;
int cnt[N*4],val[N*4],sum[N*4],mul[N*4];
int mypow(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)
            res=(LL)res*a%MOD;
        a=(LL)a*a%MOD;
        b>>=1;
    }
    return res;
}
int qa[N],qb[N];
void build(int l,int r,int i)
{
    cnt[i]=sum[i]=0;
    mul[i]=1;
    if(l==r)
    {
        val[i]=mypow(3,qb[l]);
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,lson);
    build(mid+1,r,rson);
}
void pushdown(int i)
{
    if(mul[i]!=1)
    {
        mul[lson]=(LL)mul[lson]*mul[i]%MOD;
        mul[rson]=(LL)mul[rson]*mul[i]%MOD;
        sum[lson]=(LL)sum[lson]*mul[i]%MOD;
        sum[rson]=(LL)sum[rson]*mul[i]%MOD;
        mul[i]=1;
    }
}
void pushup(int i)
{
    cnt[i]=cnt[lson]+cnt[rson];
    sum[i]=(sum[lson]+sum[rson])%MOD;
}
void update(int l,int r,int pl,int pr,int type,int va,int i)
{
    if(l>=pl&&r<=pr)
    {
        if(type==1)
        {
            mul[i]=(LL)mul[i]*va%MOD;
            sum[i]=(LL)sum[i]*va%MOD;
        }else
        {
            cnt[i]++;
            sum[i]+=(LL)val[i]*va%MOD;
            if(sum[i]>=MOD)sum[i]-=MOD;
        }
        return ;
    }
    pushdown(i);
    int mid=(l+r)>>1;
    if(mid>=pl)update(l,mid,pl,pr,type,va,lson);
    if(pr>mid)update(mid+1,r,pl,pr,type,va,rson);
    pushup(i);
}
int query(int l,int r,int pl,int pr,int type,int i)
{
    if(l>=pl&&r<=pr)
    {
        if(type==1)return sum[i];
        else return cnt[i];
    }
    pushdown(i);
    int mid=(l+r)>>1;
    int tmp=0;
    if(pl<=mid)tmp+=query(l,mid,pl,pr,type,lson);
    if(pr>mid)tmp+=query(mid+1,r,pl,pr,type,rson);
    if(tmp>=MOD)tmp-=MOD;
    return tmp;
}
struct node
{
    int a,b;
}s[N];
bool cmp(node a,node b)
{
    return a.a<b.a;
}
int main() {
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int taila,tailb;
        taila=tailb=0;
        for(int i=0;i<n;++i)
        {
            scanf("%d%d",&s[i].a,&s[i].b);
            qa[taila++]=s[i].a;
            qb[tailb++]=s[i].b;
        }
        sort(s,s+n,cmp);
        sort(qa,qa+taila);
        sort(qb,qb+tailb);
        taila=unique(qa,qa+taila)-qa;
        tailb=unique(qb,qb+tailb)-qb;
        int maxn=tailb-1;
        build(0,maxn,1);
        int ans=0;
        for(int i=0;i<n;++i)
        {
            int x=lower_bound(qb,qb+tailb,s[i].b)-qb;
            int tmp=(LL)mypow(2,s[i].a)*mypow(3,s[i].b)%MOD;
            int cc=0;
            if(x>0)
            {
                cc=query(0,maxn,0,x-1,2,1);
                tmp=(LL)tmp*mypow(2,cc)%MOD;
            }
            int tmp2=(LL)mypow(2,s[i].a)*query(0,maxn,x,maxn,1,1)%MOD;
            tmp+=tmp2;
            if(tmp>=MOD)tmp-=MOD;
            ans+=tmp;
            if(ans>=MOD)ans-=MOD;
        //    printf("::%d %d\n",x,maxn);
            update(0,maxn,x,maxn,1,2,1);
            update(0,maxn,x,x,2,mypow(2,cc),1);
        }
        printf("%d\n",(ans%MOD+MOD)%MOD);
    }

    return 0;
}

 

posted on 2014-08-06 19:07  L_Ecry  阅读(513)  评论(0编辑  收藏  举报