题意:求所有自己的最小公倍数的和。 该集合是 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 ",x,maxn); update(0,maxn,x,maxn,1,2,1); update(0,maxn,x,x,2,mypow(2,cc),1); } printf("%d ",(ans%MOD+MOD)%MOD); } return 0; }