ans = sigma_x(sigma_y(gcd(x,y) * 2 - 1)),1<=x<=n,1<=y<=m
枚举x,y,O(nmlogn),超时
换个角度,枚举d = gcd(x,y)
d对ans的贡献为2*d-1
若有n个(x,y)使得gcd(x,y) = d,则贡献为n * (2 * d - 1)
f(d) 表示gcd(x,y) = d 的(x,y)个数
ans = sigma(f[d] * (2 * d - 1)),1 <= d <= min(n,m)
那么问题就是求f(d)
g(d) 表示d|gcd(x,y)的(x,y)个数
则g(d) = (n / d) * (m / d)
f(d) = g(d) - f(i * d) , 2 <= i <= min(n,m) / d
反序遍历d,即min(n,m) 到 1
求f(d),累加f(d) * (2 * d - 1) 到ans
O(nlogn)
//File Name: bzoj2005.cpp //Author: long //Mail: 736726758@qq.com //Created Time: 2016年02月12日 星期五 14时08分18秒 #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #define LL long long using namespace std; const int MAXN = 100000+5; LL f[MAXN]; void solve(int n,int m) { LL ans = 0LL; int mi = min(n,m); memset(f,0,sizeof f); for(int i=mi;i>0;i--){ f[i] = (LL)(n/i) * (m/i); for(int j=2;j<=mi/i;j++){ f[i] -= f[j*i]; } ans += f[i] * (i * 2LL - 1); } cout << ans << endl; return ; } int main() { int n,m; while(~scanf("%d %d",&n,&m)){ solve(n,m); } return 0; }