51nod 1188 最大公约数之和 V2

https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1188


给出一个数N,输出小于等于N的所有数,两两之间的最大公约数之和。

 

本来和bzoj的2705有类似  改了改还是TLE,发现有重复的地方 借鉴了下别人的代码把核心求phi(x)*y 拿出来预处理就好了 用了快读优化 交第一次最后一点TLE  交第二次就过了 最后一个点1600+ms,不是很懂这个评测机。。。


#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<set>
#define LL long long
using namespace std;
LL N,M,T;
long long read(){
	long long x=0,f=1;char ch=getchar();
	while(!(ch>='0' && ch<='9')){ch=getchar();if(ch=='-') f=-1;}
	while(ch>='0' && ch<='9'){x=x*10+(ch-'0');ch=getchar();}
	return x*f;
}
	
LL sum[5150000];
LL phi[5150000],prime[5150000],tot;
bool check[5150000]; 
LL F[5100000];
void getphi(int gg){
	phi[1]=1;
	for(int i=2;i<=gg;i++){
		if(!check[i])  {tot++;prime[tot]=i;phi[i]=i-1;}
		for(int j=1;j<=tot;j++){
			if(i*prime[j]>gg) break;
			check[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]*phi[prime[j]];
		}
	}
} 

LL Sum[5111000]={0};
LL fun(LL x)
{
	for(LL  i=1;i<=x;i++) 
		for(LL j=2;j<=x/i;j++) 
			Sum[i*j]+=i*phi[j];
}

void init(int g)
{
	F[0]=0;sum[0]=0;Sum[0]=0;
	
	fun(g);
	
	for(int i=1;i<=g;i++)
	{
		F[i]=F[i-1]+Sum[i];
	}
}
LL SS[10000000/2+1000];
int main()
{

	phi[0]=0;
	
	scanf("%d",&T);
	LL MX=0;
	for(int i=1;i<=T;i++)SS[i]=read(),MX=max(MX,SS[i]);
	getphi(MX+1000);init(MX);
	
	int i=1;
	while(T--)
	{
		//scanf("%d",&N);
		//N=read();
		N=SS[i++];
		LL ans=0;
		ans=F[N];
		printf("%lld\n",ans);
		
	}

	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值