51nod 1188 最大公约数之和 V2


第二个\( O(T\sqrt(n)) \)复杂度T了..T了..T了...天地良心,这能差多少?!
于是跑去现算(。

\[\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}gcd(i,j) \]

\[\sum_{d=1}^{n}d\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}[gcd(i,j)==d] \]

\[\sum_{d=1}^{n}d(\sum_{j=1}^{n}\sum_{i=1}^{j}[gcd(i,j)==d]-\sum_{j=1}^{n}[gcd(j,j)==d]) \]

\[\sum_{d=1}^{n}d(\sum_{j=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\sum_{i=1}^{j}[gcd(i,j)==1]-1) \]

\[\sum_{d=1}^{n}d(\sum_{j=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\phi(j)-1) \]

然后与\( O(nlnn) \)处理出所有答案。

#include<iostream>
#include<cstdio>
using namespace std;
const int N=5000005,m=5000000;
int T,n,phi[N],q[N],tot;
long long s[N],ans[N],con;
bool v[N];
int main()
{
	phi[1]=1;
	for(int i=2;i<=m;i++)
	{
		if(!v[i])
		{
			q[++tot]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=tot&&i*q[j]<=m;j++)
		{
			int k=i*q[j];
			v[k]=1;
			if(i%q[j]==0)
			{
				phi[k]=phi[i]*q[j];
				break;
			}
			phi[k]=phi[i]*(q[j]-1);
		}
	}
	for(int i=1;i<=m;i++)
		for(int j=2;j<=m/i;j++)
			ans[i*j]+=phi[j]*i;
	for(int i=1;i<=m;i++)
		ans[i]+=ans[i-1];
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		printf("%lld\n",ans[n]);
	}
	return 0;
}
posted @ 2018-01-19 21:18  lokiii  阅读(144)  评论(0编辑  收藏  举报