题目地址:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2421
题意简单。
题解:
设f(n)=gcd(1,n)+gcd(2,n)+……+gcd(n-1,n);s(n)=f(1)+f(2)+……f(n).所以有s(n)=s(n-1)+f(n).现在关键是求f(n)。
设g(n,i)表示所有满足gcd(x,n)=i的正整数x的个数i<n,那么f(n)=sum(i*g(n,i)),i的n的约数,gcd(x,n)=i -> gcd(x/i,n/i)=1,所以满足条件的x/i有phi(n/i)个。
但是如果依次计算f(n),需要枚举n的所以约数,如果吧思路逆过来,对每个i枚举他的倍数并更新f(n),时间复杂度就很小了。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
using namespace std;
typedef long long LL;
const int N=4000001;
const int mod=1000007;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
LL phi[N],xh[N];
void phi_table()
{
int i,j;
memset(phi,0,sizeof(phi));
xh[1]=0;
phi[1]=1;
for(i=2;i<=N;i++)
{
if(!phi[i])
{
for(j=i;j<=N;j+=i)
{
if(!phi[j])
phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
for(j=i;j<=N;j+=i)
xh[j]+=j/i*phi[i];
}
for(i=2;i<=N;i++)
xh[i]+=xh[i-1];
}
int main()
{
int n,i,j;
phi_table();
while(cin>>n&&n)
{
printf("%lld\n",xh[n]);
}
return 0;
}