51nod 1190 最小公倍数之和 V2【莫比乌斯反演】

参考:http://blog.csdn.net/u014610830/article/details/49493279
这道题做起来感觉非常奇怪啊……头一次见把mu推出来再推没了的……

[sum_{i=a}^{b}lcm(i,b) ]

[sum_{i=a}^{b}frac{i*b}{gcd(i,b)} ]

[sum_{d|b}sum_{i=a}^{b}[gcd(i,b)==d]frac{ib}{d} ]

[sum_{d|b}sum_{i=left lfloor frac{a}{d} ight floor}^{left lfloor frac{b}{d} ight floor}[gcd(i,b)==1]frac{idb}{d} ]

[bsum_{d|b}sum_{i=left lfloor frac{a}{d} ight floor}^{left lfloor frac{b}{d} ight floor}[gcd(i,b)==1]i ]

[bsum_{d|b}sum_{i=left lfloor frac{a}{d} ight floor}^{left lfloor frac{b}{d} ight floor}isum_{k|gcd(i,frac{b}{d})}mu(k) ]

[bsum_{d|b}sum_{k|frac{b}{d}}mu(k)sum_{i=left lfloor frac{a}{d} ight floor}^{left lfloor frac{b}{d} ight floor,k|i}i ]

[bsum_{d|b}sum_{k|frac{b}{d}}mu(k)ksum_{i=left lfloor frac{a}{dk} ight floor}^{left lfloor frac{b}{dk} ight floor}i ]

[f(a,b)=sum_{i=a}^{b}i ]

[bsum_{d|b}sum_{k|frac{b}{d}}mu(k)kf(left lfloor frac{a}{dk} ight floor,left lfloor frac{b}{dk} ight floor) ]

枚举dk

[bsum_{d|b}f(frac{a}{d},frac{b}{d})sum_{k|d}mu(k)k ]

其中f可以( O(1) )算,设( g(x)=sum_{k|x}mu(k)k ),容易发现这是积性的,显然设p为质数,( g(p)=1-p,g(p^k)=1-p ),于是这样就把mu推掉了
时间复杂度很不科学但是还是能过

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int N=100005,m=100000,inv2=500000004,mod=1e9+7;
int T,n,q[N],tot,a,b,p[N],cnt,len[N];
bool v[N];
vector<int>fac;
void dfs(int re,int l)
{
	if(l>cnt)
	{
		fac.push_back(re);
		return;
	}
	int tmp=1;
	dfs(re,l+1);
	for(int i=1;i<=len[l];i++)
	{
		tmp*=p[l];
		dfs(re*tmp,l+1);
	}
}
int main()
{
	v[1]=1;
	for(int i=2;i<=m;i++)
	{
		if(!v[i])
			q[++tot]=i;
		for(int j=1;j<=tot&&i*q[j]<=m;j++)
		{
			int k=i*q[j];
			v[k]=1;
			if(i%q[j]==0)
				break;
		}
	}
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&a,&b);
		cnt=0;
		int now=b;
		for(int i=1;i<=tot&&q[i]*q[i]<=now;i++)
		{
			if(now%q[i]==0)
			{
				p[++cnt]=q[i];
				len[cnt]=0;
			}
			while(now%q[i]==0)
			{
				now/=q[i];
				len[cnt]++;
			}
		}
		if(now>1)
		{
			p[++cnt]=now;
			len[cnt]=1;
		}
		fac.clear();
		dfs(1,1);//cout<<cnt<<endl;
		long long ans=0ll;
		for(int i=0;i<fac.size();i++)
		{
			int v=fac[i];
			long long tt=a+v-1,tmp,re=1ll;
			tmp=(((tt/v+b/v)%mod)*((b/v-tt/v+1+mod)%mod)%mod)*inv2%mod;
			for(int j=1;j<=cnt;j++)
				if(v%p[j]==0)
					re=re*((1-p[j]+mod)%mod)%mod;
			ans=((ans+re*tmp%mod)%mod+mod)%mod;
		}
		printf("%lld
",ans*b%mod);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/lokiii/p/8320189.html