2016暑期集训2-I
POJ 2480 Longge’s problem
数论,欧拉函数变形
传送门:HustOJ
传送门:POJ
题意
给了N(最大2^31),求∑gcd(i, N) ,1<=i <=N。
思路
欧拉函数可知,在1···N中,gcd(i,N) = 1, 的个数的等于φ(N),因为模的特性,取模和乘法可以交换运算,所以在1···N中,gcd(i,N) = x, 的个数的等于φ(N / x)。可以写几个例子推一下。所以,f(N)=∑x*φ(N/x),x | N (x是N的约数)。对于每个N的约数(不仅仅是质因数!),求一下φ(N/x)的值。这里有几点注意:
- 这个欧拉函数不能打表,因为2^31太大了,打不下,需要一个个的求。
- 求约数的过程不能用O(n)的,要用O(根号n)的,否则会超时。x是约数,如果x*x不等于N,那么N/x也是约数。
代码
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<iomanip>
using namespace std;
typedef long long ll;
ll phi ( ll n )
{
ll tn = n;
ll phi = n;
for ( ll i = 2; ( i*i <= n ); i++ )
{
if ( tn % i == 0 )
{
phi = phi*( i - 1 ) / i ;
}
while ( tn % i == 0 )
{
tn /= i;
}
}
if ( tn > 1 )
{
phi = phi*( tn - 1 ) / tn ;
}
return phi;
}
int main ( )
{
ll n;
while ( ~scanf ( "%lld" , &n ) )
{
ll res = 0;
for ( ll i = 1; i*i <= n; i++ )
{
if ( n%i == 0 )
{
if ( i*i == n )
{
res += ( i*phi ( n / i ) );
}
else
{
res += ( i*phi ( n / i ) + ( n / i )*phi ( i ) );
}
}
}
printf ( "%lld\n" , res );
}
//system ( "pause" );
return 0;
}