您的位置:首页 > 其它

POJ2480——Longge's problem(数论,欧拉函数d)

2016-07-20 22:21 555 查看
题目:

Longge's problem

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 8050 Accepted: 2666
Description

Longge is good at mathematics and he likes to think about hard mathematical problems which will be solved by some graceful algorithms. Now a problem comes: Given an integer N(1 < N < 2^31),you are to calculate ∑gcd(i, N) 1<=i <=N. 

"Oh, I know, I know!" Longge shouts! But do you know? Please solve it. 

Input

Input contain several test case. 

A number N per line. 

Output

For each N, output ,∑gcd(i, N) 1<=i <=N, a line
Sample Input
2
6

Sample Output
3
15


大意:就是求[1,n]的整数和n的最大公约数的和

思路:肯定不能暴力。区间是[1,n],数是n,马上就想到欧拉函数。怎么联系起来?欧拉函数是求互质的数的个数。比如如果n能整除2,那么与n最大公约数为2的数的个数为区间[1,n/2]里头与n/2互质的数的个数。那么和就是phi[n/2]*2。

怎么降低复杂度呢?还是拿2举例子。n/2肯定也是n的约数,那么再加上phi[2]*n/2即可。

代码如下

#include <cmath>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <algorithm>
#include <string>
#include <set>
#include <cmath>

using namespace std;
typedef long long ll;
const int Max=100010;
ll p[Max];
bool is_prime[Max];

ll euler(ll n){
ll res=n,a=n;
for(int i=0;p[i]*p[i]<=a;i++){
if(a%p[i]==0){
res=res/p[i]*(p[i]-1);
while(a%p[i]==0) a/=p[i];
}
}
if(a>1) res=res/a*(a-1);
return res;
}

int main()
{
ll n;
int k=0;
for(int i=0;i<Max;i++)
is_prime[i]=true;
for(int i=2;i<Max;i++)
{
if(is_prime[i])
{
for(int j=2*i;j<Max;j+=i)
is_prime[j]=false;
p[k++]=i;
}
}
while(scanf("%lld",&n)!=EOF)
{
ll sq=(int)sqrt((double)n);
ll ans=0;
for(int i=1;i<=sq;i++)
{
if(i*i==n)
{
ans+=euler(i)*i;
}
else if(n%i==0)
{
long long s=n/i;
ans+=euler(s)*i+euler(i)*s;
}
}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: