bzoj3529: [Sdoi2014]数表 (莫比乌斯反演)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sunshiness_s/article/details/80322523

题意

bzoj3529
就是求i=1nj=1mσ(gcd(i,j))σ(gcd(i,j)<=a


题解

先不去考虑a这个限制
那么就等于

=i=1nj=1md|gcd(i,j)d=d=1nσ(d)i=1nj=1mgcd(i,j)==d=d=1nσ(d)i=1ndj=1mdgcd(i,j)==1=d=1nσ(d)i=1ndj=1mdϵ(gcd(i,j))=d=1nσ(d)k=1ndμ(k)nkdmkd

σμ都是可以预处理求出来的

然后再去考虑a这个限制,可以发现每个格子里面的结果就是对应的σ(gcd(i,j)),因此只要σa 就可以了
因此用树状数组维护σ.......

我不会说…我改了很久…是因为….100000写成了10000【再见再见再见】
当时以为是ll的错【再见再见再见】


代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; 
#define N 100010
int mu[N],sig[N],prime[N],n,tot=0,ms[N],tree[N],ans[N];
bool notprime[N];
struct node{int x,y,a,num;}q[N];
struct node1{int sig,num;}f[N]; 
bool cmp(node x,node y){return x.a<y.a;}
bool cmp1(node1 x,node1 y){return x.sig<y.sig;}
void mobius(){
    mu[1]=1;sig[1]=1;ms[1]=1;
    memset(notprime,false,sizeof(notprime));notprime[1]=true;
    for(int i=2;i<=100000;i++){
        if(!notprime[i]) prime[++tot]=i,mu[i]=-1,sig[i]=i+1,ms[i]=i;
        for(int j=1;j<=tot,prime[j]*i<=100000;j++){
            notprime[i*prime[j]]=true;
            if(i%prime[j]==0){
                ms[prime[j]*i]=ms[i]*prime[j];mu[prime[j]*i]=0;
                if(ms[i]==i) sig[i*prime[j]]=(i*prime[j]*prime[j]-1)/(prime[j]-1);
                else sig[i*prime[j]]=sig[i/ms[i]]*sig[prime[j]*ms[i]];
                break;
            }mu[i*prime[j]]=-mu[i];sig[i*prime[j]]=sig[i]*sig[prime[j]];ms[i*prime[j]]=prime[j];
        }
    }
}
void add(int x,int y){
    for(int i=x;i<=100000;i+=i&-i) tree[i]+=y;
}
int query(int x){
    int sum=0;
    for(int i=x;i;i-=i&-i) sum+=tree[i];
    return sum;
}
void change(int &now,int a){
    while(now<=100000 && a>=f[now].sig){
            for(int j=1;f[now].num*j<=100000;j++) 
                add(f[now].num*j,f[now].sig*mu[j]);
            now++;
        }
}
int solve(int x,int y){
    int res=0;if(x>y) swap(x,y);
    for(int j=1,last=0;j<=x;j=last+1){
        last=min(x/(x/j),y/(y/j));
        res+=(query(last)-query(j-1))*(x/j)*(y/j);
    }return res&0x7fffffff;
}
int main(){
    scanf("%d",&n);mobius();
    for(int i=1;i<=100000;i++) f[i].sig=sig[i],f[i].num=i;
    sort(f+1,f+100000+1,cmp1);
    for(int i=1;i<=n;i++) scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].a),q[i].num=i;
    sort(q+1,q+n+1,cmp);
    for(int i=1,now=1;i<=n;i++){
        change(now,q[i].a);
        ans[q[i].num]=solve(q[i].x,q[i].y);
    }for(int i=1;i<=n;i++) printf("%d\n",ans[i]&0x7fffffff);
    return 0;
} 
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页