题意
给定一个数,求,其中表示的是的数位和。
思路
题目要我们求对于每个数,所有与互质的的和。
可以将其转化成反向的:对于每个数,所有与互质的数的个数,这就是的权重。
这一对称情况忽视了对角线上的,所以要将其补上。
本题亦可使用莫比乌斯反演推导。
solution
#include <bits/stdc++.h> using namespace std; #define sc(x) scanf("%lld", &(x)) #define pr(x) printf("%lld", (x)) const int N = 1e5 + 7; typedef long long ll; bool vis[N]; int cnt; ll f[N]; //数位和 vector<int> prime; //质数表 vector<int> p[N]; // p[i]里存着i的所有质因子 inline int getf(int x) { int res = 0; while (x) { res += x % 10; x /= 10; } return res; } inline void pre(ll n) { for (int i = 2; i < N; ++i) { //筛出所有质数 if (!vis[i]) ++cnt, prime.push_back(i); for (int j = 0; j < cnt && i * prime[j] < N; ++j) { vis[i * prime[j]] = 1; if (i % prime[j] == 0) break; } } for (int i = 2; i <= n; ++i) { //筛出每个数所有的质因数 int x = i; for (int j = 0; j < cnt && prime[j] * prime[j] <= x; ++j) { if (x % prime[j] == 0) { p[i].push_back(prime[j]); while (x % prime[j] == 0) x /= prime[j]; } } if (x != 1) p[i].push_back(x); } for (int i = 1; i <= n; ++i) f[i] = getf(i); //得到每个数的数位和 } int main() { ll n; sc(n); pre(n); //对于每一个i,找[i+1,n]里有多少个个数和它互质 // fi*数量 即是权重 ll ans = 0; for (int i = 1; i < n; ++i) { int m = p[i].size(); ll tmp = 0; // 与i不互质的数的个数 for (int j = 1; j < 1 << m; ++j) { int c = __builtin_popcount(j); //选中了多少个因数 ll op = (c & 1) ? 1 : -1; //容斥奇加偶减 ll ret = 1; //当前枚举状态的所有质因数的乘积 for (int k = 0; k < m; ++k) if (j & (1 << k)) ret *= p[i][k]; ll now = (n - i) / ret; //有多少个数是ret的倍数 tmp += op * now; } ans += (n - i - tmp) * f[i]; } pr(ans + 1); //gcd(1,1)未被计算 return 0; }
出题人题解