【BZOJ2693】jzptab(莫比乌斯反演)

【BZOJ2693】jzptab(莫比乌斯反演)

题面

讨厌权限题,只能跑到别的OJ上交
这题是一样的
多组数据
求$$\sum_{i=1}n\sum_{j=1}mlcm(i,j)$$

题解

前面的部分直接看上面的那个链接

\[ans=\sum_{d=1}^nd\sum_{i=1}^{n/d}i^2S(\frac{n}{id})S(\frac{m}{id})\mu(i) \]

其中\(S(x)=1+2+...x=\frac{x(x+1)}{2}\)
\(T=id\)

\[ans=\sum_{T=1}^nS(\frac{n}{T})S(\frac{m}{T})\sum_{d|T}d^2\frac{T}{d}\mu(d) \]

\(f(x)=x^2\mu(x)\),\(g(x)=\frac{T}{x}\)
很显然,这两个都是积性函数
所以,后面的东西也是积性函数
直接线性筛出来就行了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MOD 100000009
#define MAX 10000000
inline int read()
{
	int x=0,t=1;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=-1,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return x*t;
}
bool zs[MAX+10];
int sum[MAX+10],pri[MAX],tot;
void pre()
{
	zs[1]=true;sum[1]=1;
	for(int i=2;i<=MAX;++i)
	{
		if(!zs[i])pri[++tot]=i,sum[i]=(i-1ll*i*i%MOD+MOD)%MOD;
		for(int j=1;j<=tot&&i*pri[j]<=MAX;++j)
		{
			zs[i*pri[j]]=true;
			if(i%pri[j]==0){sum[i*pri[j]]=1ll*sum[i]*pri[j]%MOD;break;}
			else sum[i*pri[j]]=1ll*sum[i]*sum[pri[j]]%MOD;
		}
	}
	for(int i=1;i<=MAX;++i)sum[i]=(sum[i-1]+sum[i])%MOD;
}
int n,m;
int main()
{
	pre();
	int T=read();
	while(T--)
	{
		n=read();m=read();
		if(n>m)swap(n,m);
		int i=1,j;
		long long ans=0;
		while(i<=n)
		{
			j=min(n/(n/i),m/(m/i));
			int tt=(1ll*(1+n/i)*(n/i)/2%MOD)*(1ll*(1+m/i)*(m/i)/2%MOD)%MOD;
			ans+=1ll*(sum[j]-sum[i-1]+MOD)%MOD*tt%MOD;
			ans%=MOD;
			i=j+1;
		}
		printf("%lld\n",(ans+MOD)%MOD);
	}
	return 0;
}

posted @ 2018-01-11 12:47  小蒟蒻yyb  阅读(1053)  评论(0编辑  收藏  举报