• bzoj 3529


    非常好的一道莫比乌斯反演题,对提升自己的能力有很大帮助。

    首先我们分析一下题意:题意让我们求sum_{k=1}sigma(k)sum_{i=1}^{n}sum_{j=1}^{m}[gcd(i,j)==k],其中sigma(k)leq a

    那么我们首先对后面的式子进行一下变形,变形过程详见https://blog.csdn.net/lleozhang/article/details/89093689

    于是最后变成了这个样子:

    sum_{k=1}sigma(k)sum_{k|d}mu(d/k)*[n/d]*[m/d]

    但是这个式子还是不好,所以我们改变一下枚举顺序,先枚举d

    于是上式改为:

    sum_{d=1}^{n}[n/d]*[m/d]sum_{k|d}sigma(k)*mu(d/k)

    可以发现右侧的式子是一个反演的形式,于是记f(d)=sum_{k|d}sigma(k)*mu(d/k)

    于是原式=sum_{d=1}^{n}[n/d]*[m/d]*f(d)

    先预处理出每个数的约数和(线性筛),然后利用数论分块+前缀和计算即可

    等等,难道就这么简单?

    当然不会了!!!

    再仔细想想,我们上面的过程根本没有管a啊!

    由于对k是有要求的,所以我们在预处理的时候如果不知道询问中的a,就没有办法确认对于每个d,哪个k是可用的!

    那怎么办?

    离线!

    我们先将所有询问按照a从小到大排序,这样前面的询问所能用到的k后面的询问一定也可以用,这样我只需要每次将因为a变大而变得可用的k加入即可!

    可是我们的要求是sigma(k)leq a,所以仅仅对a排序是不够的,由于约数和并不具有单调性,所以我们还要对约数和排序,然后对于每个询问,将新变得合法的k对应地累计进f(d)就可以了

    由于这是一个动态的过程,使用树状数组维护f的前缀和,这样就既支持修改,又支持求前缀和了。

    贴代码:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    #define mode (1ll<<31)
    using namespace std;
    struct Ques
    {
    	int n,m,a,num;
    }q[100005];
    int pri[100005];
    bool used[100005];
    int mu[100005];
    struct SIG
    {
    	ll si;
    	int num;
    }sig[100005];
    int mi[100005];
    ll v[100005];
    ll ret[100005];
    int s[100005];
    int cnt=0;
    int lowbit(int x)
    {
    	return x&(-x);
    }
    void ins(int x,ll y)
    {
    	while(x<=100000)
    	{
    		s[x]+=y;
    		x+=lowbit(x);
    	}
    }
    int get_sum(int x)
    {
    	int ans=0;
    	while(x)
    	{
    		ans+=s[x];
    		x-=lowbit(x);
    	}
    	return ans;
    }
    ll pow_mul(ll x,int y)
    {
    	ll ans=1;
    	while(y)
    	{
    		if(y&1)
    		{
    			ans*=(ll)x;
    		}
    		x*=x;
    		y/=2;
    	}
    	return ans;
    }
    void init()
    {
    	mu[1]=1;
    	sig[1].si=1;
    	sig[1].num=1;
    	for(int i=2;i<=100000;i++)
    	{
    		if(!used[i])
    		{
    			pri[++cnt]=i;
    			mu[i]=-1;
    			sig[i].si=i+1;
    			sig[i].num=i;
    			v[i]=i+1;
    			mi[i]=1;
    		}
    		for(int j=1;j<=cnt&&i*pri[j]<=100000;j++)
    		{
    			used[i*pri[j]]=1;
    			if(i%pri[j]==0)
    			{
    				mu[i*pri[j]]=0;
    				ll temp=v[i]+pow_mul(pri[j],mi[i]+1);
    				sig[i*pri[j]].si=sig[i].si/v[i]*temp;
    				sig[i*pri[j]].num=i*pri[j];
    				mi[i*pri[j]]=mi[i]+1;
    				v[i*pri[j]]=temp;
    				break;
    			}
    			mu[i*pri[j]]=-mu[i];
    			sig[i*pri[j]].si=sig[i].si*(pri[j]+1);
    			sig[i*pri[j]].num=i*pri[j];
    			v[i*pri[j]]=pri[j]+1;
    			mi[i*pri[j]]=1;
    		}
    	}
    }
    bool cmp(Ques x,Ques y)
    {
    	return x.a<y.a;
    }
    bool cmp1(SIG x,SIG y)
    {
    	return x.si<y.si;
    }
    int solve(int x,int y)
    {
    	if(x>y)
    	{
    		swap(x,y);
    	}
    	int ans=0;
    	int last=0;
    	for(int i=1;i<=x;i=last+1)
    	{
    		last=min(x/(x/i),y/(y/i));
    		ans+=(get_sum(last)-get_sum(i-1))*(x/i)*(y/i);
    	}
    	return ans;
    }
    int T;
    inline int read()
    {
    	int f=1,x=0;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    int main()
    {
    	T=read();
    	init();
    	int maxn=0;
    	for(int i=1;i<=T;i++)
    	{
    		q[i].n=read(),q[i].m=read(),q[i].a=read();
    		q[i].num=i;
    		maxn=max(maxn,max(q[i].n,q[i].m));
    	}
    	sort(q+1,q+T+1,cmp);
    	sort(sig+1,sig+100001,cmp1);
    	int las=1;
    	for(int i=1;i<=T;i++)
    	{
    		while(sig[las].si<=q[i].a&&las<=100000)//枚举k 
    		{ 
    			for(int j=1;j*sig[las].num<=maxn;j++)//枚举倍数 
    			{
    				ins(j*sig[las].num,sig[las].si*mu[j]);
    			}
    			las++;
    		}
    		ret[q[i].num]=solve(q[i].n,q[i].m)&2147483647;
    	}
    	for(int i=1;i<=T;i++)
    	{
    		printf("%d
    ",ret[i]);
    	}
    	return 0;
    }
  • 相关阅读:
    爬虫学习
    手刃爬虫豆瓣
    爬虫学习
    爬虫学习
    安卓学习新
    安卓知识点
    随手快递app开发的第十天
    随手快递app冲刺2开发的第九天
    随手快递app冲刺2开发的第八天
    随手快递app冲刺2开发的第七天
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10764138.html
Copyright © 2020-2023  润新知