UVa - 11426
给定一个 N,数对 i,j <= N且 i < j
求所有数对的 gcd(i,j)的和
其中 N <= 4e6
这是大白 p125的例题
首先按题目描述两个for肯定是不行的
所以我们反过来考虑,一个数是多少对数的gcd
换句话来说,就是一个数被加了几次
于是我们枚举这个gcd为i
设有数对
a=a′∗i,b=b′∗i
其中a′,b′互质且 a′<b′
那么对于一个b′,小于他的数有多少个与它互质呢
答案是 ϕ(b′)
于是我们就能得到对于一个数b,有多少个
时间复杂度O(N∗(ln(n)+C)),其中C是欧拉常数
所以问题就得到解决了
关于一个数的因子或
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DBL;
typedef long double LDBL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Pow2(a) (a*a)
const int maxn=4e6+10;;
int N;
int phi[maxn];
LL sum[maxn],ans[maxn];
void init_phi(int);
int main()
{
init_phi(maxn);
for(int i=1; i<maxn; i++) for(int j=i*2; j<maxn; j+=i)
sum[j]+=(LL)i*phi[j/i];
ans[2]=sum[2];
for(int i=3; i<maxn; i++) ans[i]=ans[i-1]+sum[i];
while(~scanf("%d", &N)&&N)
{
printf("%lld\n", ans[N]);
}
return 0;
}
void init_phi(int Lim)
{
for(int i=1; i<Lim; i++) phi[i]=i;
for(int i=2; i<Lim; i++)
{
if(phi[i]<i) continue;
for(int j=i; j<Lim; j+=i) phi[j]=phi[j]/i*(i-1);
}
}