题目链接:https://ac.nowcoder.com/acm/contest/8827/A
枚举 (gcd),则答案应为
[sumlimits_{d=1}^n mu(d) sumlimits_{i=1}^{lfloor frac{n}{d}
floor} sumlimits_{j=1}^{lfloor frac{i}{d}
floor} F(jd)
]
交换 (i,j) 的枚举顺序,得到
[sumlimits_{d=1}^n mu(d) sumlimits_{j=1}^{lfloor frac{n}{d}
floor} F(jd)(lfloor frac{n}{d}
floor-j+1 )
]
枚举倍数 (O(nlogn)) 计算即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100010;
int n;
int cnt = 0;
int prime[maxn], mu[maxn], is_prime[maxn];
int f[maxn];
int count(int x){
int tmp = x;
int res = 0;
while(tmp){
res += tmp % 10;
tmp /= 10;
}
return res;
}
ll solve(int d){
ll res = 0;
for(int i = 1 ; i * d <= n ; ++i){
res += 1ll * f[i*d] * (n/d-i+1);
}
return 1ll * res * mu[d];
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
mu[1] = 1;
for(int i = 2; i <= 100000; ++i){
if(!is_prime[i]){
prime[++cnt] = i;
mu[i] = -1;
}
for(int j = 1 ; j <= cnt && prime[j] * i <= 100000 ; ++j){
is_prime[i * prime[j]] = 1;
if(i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
} else {
mu[i * prime[j]] = -mu[i];
}
}
}
n = read();
for(int i = 1 ; i <= n ; ++i){ f[i] = count(i); }
ll ans = 0;
for(int d = 1 ; d <= n ; ++d){
ans += solve(d);
}
printf("%lld
", ans);
return 0;
}