您的位置:首页 > 其它

51nod 1188 最大公约数之和 V2

2016-10-28 20:39 405 查看
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
;
printf("%lld\n",ans);

}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: