bzoj2705Longge的问题

题目链接

题意很简单

$$ans=\sum_{i=1}^{n}gcd(i,n)$$

然后推一下式子,求一下欧拉函数就好了

细节是由于$BZOJ$的评测计时策略,

不能线性筛啊$……$

必须每个数单独筛

一开始线性筛洛谷上过了,$BZ$果断$T$

/**************************************************************
    Problem: 2705
    User: zhangheran
    Language: C++
    Result: Accepted
    Time:28 ms
    Memory:89184 kb
****************************************************************/
 
#pragma GCC optimize (2)
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int cnt;
int prime[10000010];
int phi[10000010];
bool ins[10000010];
void Euler()
{
    phi[1]=1;
    for(int i=2;i<=10000000;i++){
      if(!ins[i]) prime[++cnt]=i,phi[i]=i-1;
      for(int j=1;j<=cnt&&i*prime[j]<=10000000;j++){
        ins[i*prime[j]]=true;
        if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}
        else phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
    return ;
}
long long getphi(long long n)
{
//  if(n<10000000) return phi[n];
    long long res=n;
    for(long long i=2;i*i<=n;i++){
        if(n%i==0) res=res/i*(i-1);
        while(n%i==0) n/=i;
    }
    if(n>1) res=res/n*(n-1);
    return res;
}
long long x;
long long ans;
int main()
{
//  freopen("1.in","r",stdin);
//  freopen("1.out","w",stdout);
    scanf("%lld",&x);
//  Euler();
    long long i=1;
    for(;i*i<x;i++) if(x%i==0) ans+=i*getphi(x/i)+(x/i)*getphi(i);
    if(i*i==x) ans+=i*getphi(i);
    printf("%lld",ans);
}
//9812

 

posted @ 2018-07-26 22:35  米罗偕涯  阅读(251)  评论(0编辑  收藏  举报