2020ICPC 江西省大学生程序设计竞赛A Simple Math Problem 莫比乌斯反演

原题链接:https://ac.nowcoder.com/acm/contest/8827/A

目录

题意

∑ i = 1 n ∑ j = 1 i [ g c d ( i , j ) = 1 ] F [ j ] \sum_{i=1}^{n}\sum_{j=1}^{i}[gcd(i,j)=1]F[j] i=1nj=1i[gcd(i,j)=1]F[j]
F [ j ] 代 表 j 各 位 数 数 字 之 和 F[j]代表j各位数数字之和 F[j]j

化简

先给式子变形一下
∑ i = 1 n ∑ j = 1 i [ g c d ( i , j ) = 1 ] F [ j ] \sum_{i=1}^{n}\sum_{j=1}^{i}[gcd(i,j)=1]F[j] i=1nj=1i[gcd(i,j)=1]F[j]

= ∑ i = 1 n F [ i ] ∑ j = i n [ g c d ( i , j ) = 1 ] =\sum_{i=1}^{n}F[i]\sum_{j=i}^{n}[gcd(i,j)=1] =i=1nF[i]j=in[gcd(i,j)=1]

= ∑ i = 1 n F [ i ] ∑ j = i n ∑ t ∣ i , t ∣ j μ ( t ) =\sum_{i=1}^{n}F[i]\sum_{j=i}^{n}\sum_{t|i,t|j}\mu(t) =i=1nF[i]j=inti,tjμ(t)

= ∑ t = 1 n μ ( t ) ∑ i = 1 n / t F [ i t ] ∑ j = i n / t 1 =\sum_{t=1}^{n}\mu(t)\sum_{i=1}^{n/t}F[it]\sum_{j=i}^{n/t}1 =t=1nμ(t)i=1n/tF[it]j=in/t1

= ∑ t = 1 n μ ( t ) ∑ i = 1 n / t F [ i t ] ( n / t − i + 1 ) =\sum_{t=1}^{n}\mu(t)\sum_{i=1}^{n/t}F[it](n/t-i+1) =t=1nμ(t)i=1n/tF[it](n/ti+1)

接着利用差分可以预处理出答案

#include <bits/stdc++.h>
using namespace std;
//#define ACM_LOCAL
#define re register
#define fi first
#define se second
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> PII;
ll prime[N], mu[N], k;
ll F[N], ans[N];
int n;
bool is_prime[N];
int get_sum(int x) {
    int ans = 0;
    while (x) {
        ans += x % 10;
        x /= 10;
    }
    return ans;
}
inline void init() {
    memset(is_prime, true, sizeof is_prime);
    mu[1] = 1;
    for (int i = 2; i < N; ++i) {
        if (is_prime[i]) prime[++k] = i, mu[i] = -1;
        for (int j = 1; j <= k && i * prime[j] < N; ++j) {
            is_prime[i * prime[j]] = false;
            if (i % prime[j] == 0) {
                break;
            } else {
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
    for (int i = 1; i <= n; i++) F[i] = get_sum(i);
    for (int t = 1; t <= n; t++) {
        ll tmp = 0;
        for (int T = t; T <= n; T += t) {
            int l = T;
            int r = min(n, l + t - 1);
            tmp += F[T] * (n/t-T/t+1);
            ans[l] += tmp * mu[t];
            ans[r+1] -= tmp * mu[t];
        }
    }
    for (int i = 1; i <= n; i++) ans[i] += ans[i-1];
}

void solve() {
    cin >> n;
    init();
    printf("%lld\n", ans[n]);
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif
    solve();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值