[bzoj2226][Spoj5971]LCMSum_欧拉函数_线性筛

LCMSum bzoj-2226 Spoj-5971

题目大意:求$\sum\limits_{i=1}^nlcm(i,n)$

注释:$1\le n\le 10^6$,$1\le cases \le 3\cdot 10^5$。


想法:$\sum\limits_{i=1}^nlcm(i,n)$

$=\sum\limits_{i=1}^n\frac{in}{gcd(i,n)}$

$=n\cdot \sum\limits_{i=1}^n \frac{i}{gcd(i,n)}$

$=n\cdot \sum\limits_{d=1}^n\sum\limits_{i=1}^{n}i/d[gcd(i,n)=d]$

$=n\cdot \sum\limits_{d|n}\sum\limits_{i=1}^{\frac{n}{d}}i[gcd(i,\frac{n}{d})=1]$

$=n\cdot \sum\limits_{d|n}\sum\limits_{i=1}^{d}i[gcd(i,d)=1]$

$=n\cdot \sum\limits_{d|n}\frac{\varphi(d)\cdot d}2$

$=n/2\cdot \sum\limits_{d|n}\varphi(d)\cdot d$

令$f(n)=\varphi(n)\cdot n$。显然是一个积性函数。所以$\sum\limits_{d|n}f(d)$是一个积性函数。所以可以线筛。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000010
using namespace std;
typedef long long ll;
const int m=1000000;
int phi[N],prime[N],tot;
ll f[N];
bool np[N];
int main()
{
	int cases,n;
	for(int i=2;i<=m;i++)
	{
		if(!np[i]) phi[i]=i-1,prime[++tot]=i;
		for(int j=1;j<=tot&&i*prime[j]<=m;j++)
		{
			np[i*prime[j]]=1;
			if(i%prime[j]==0)
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			else phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
	for(int i=2;i<=m;i++)
	{
		for(int j=i;j<=m;j+=i)
		{
			f[j]+=(ll)i*phi[i]/2;
		}
	}
	scanf("%d",&cases);
	while(cases--)scanf("%d",&n),printf("%lld\n",(f[n]+1)*n);
	return 0;
}

小结:这种题推式子就好了啊qwq。

posted @ 2018-08-26 18:20  JZYshuraK_彧  阅读(144)  评论(0编辑  收藏  举报