orz:http://www.cnblogs.com/lcf-2000/p/6250330.html
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <utility>
#include <map>
#define Mp make_pair
using namespace std;
typedef long long LL;
typedef pair<int,int> Pii;
const int MAXN=10000005;
int n,m,k,cnt,prm[MAXN>>3],mo[MAXN],f[2005],d[2005],top;
bool vis[MAXN];
map<Pii,int> g;
int gcd(int x,int y){
while(y){
swap(x,y);
y%=x;
}
return x;
}
void pre_process1(){
mo[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]){
prm[++cnt]=i;
mo[i]=-1;
}
for(int j=1;j<=cnt&&i*prm[j]<=n;j++){
vis[i*prm[j]]=1;
if(i%prm[j]==0){
mo[i*prm[j]]=0;
break;
}
mo[i*prm[j]]=-mo[i];
}
}
for(int i=1;i<=n;i++)
mo[i]+=mo[i-1];
}
void pre_process2(){
for(int i=1;i<=k;i++)
f[i]=f[i-1]+(gcd(i,k)==1);
for(int i=1;prm[i]<=k;i++)
if(k%prm[i]==0) d[++top]=prm[i];
}
int getf(int x){
return (x/k)*f[k]+f[x%k];
}
int getg(int x,int y){
if(x==0) return 0;
if(x==1) return 1;
Pii now=Mp(x,y);
if(y==0){
if(x<=MAXN-5) return mo[x];
if(g.count(now)) return g[now];
int ans=1,nxti;
for(int i=2;i<=x;i=nxti){
nxti=x/(x/i)+1;
ans-=(nxti-i)*getg(x/i,0);
}
return g[now]=ans;
}
if(g.count(now)) return g[now];
return g[now]=getg(x,y-1)+getg(x/d[y],y);
}
int main(){
n=MAXN-5;
pre_process1();
scanf("%d%d%d",&n,&m,&k);
pre_process2();
LL ans=0;int nxti;
int lim=min(n,m);
for(int i=1;i<=lim;i=nxti){
nxti=min(n/(n/i),m/(m/i))+1;
ans+=1ll*(n/i)*getf(m/i)*(getg(nxti-1,top)-getg(i-1,top));
}
printf("%lld\n",ans);
return 0;
}