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

2020ICPC 江西省大学生程序设计竞赛A-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 [ 123 ] = 1 + 2 + 3 = 6 。 F[j]为j各个数位之和,例如F[123]=1+2+3=6。 F[j]jF[123]=1+2+3=6

思路

前 置 技 能 : φ ∗ i d = μ          μ ∗ I = ε 前置技能:\red{\varphi * id=\mu\;\;\;\;\mu*I=\varepsilon } φid=μμI=ε
先 来 看 ∑ i = 1 n ∑ j = 1 i F [ j ] , 可 以 直 接 等 价 于 ∑ i = 1 n ∑ j = i n F [ i ] , 可 手 动 验 证 一 下 。 先来看\sum_{i=1}^n\sum_{j=1}^iF[j],可以直接等价于\sum_{i=1}^n\sum_{j=i}^nF[i],可手动验证一下。 i=1nj=1iF[j]i=1nj=inF[i]

∑ 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 ∑ j = i n F [ i ] ∑ d ∣ i    d ∣ j μ ( d ) \sum_{i=1}^n\sum_{j=i}^nF[i]\sum_{d|i\;d|j}\mu(d) i=1nj=inF[i]didjμ(d)

枚 举 d : 枚举d: d
∑ i = 1 n F [ i ] ∑ d ∣ i μ ( d ) ∑ ⌊ i d ⌋ ⌊ n d ⌋ 1 \sum_{i=1}^nF[i]\sum_{d|i}\mu(d)\sum_{\left \lfloor \frac{i}{d} \right \rfloor }^{\left \lfloor \frac{n}{d} \right \rfloor }1 i=1nF[i]diμ(d)didn1

∑ i = 1 n F [ i ] ( ∑ d ∣ i μ ( d ) ∗ ( n − i d ) ) \sum_{i=1}^nF[i]\left ( \sum_{d|i}\mu(d)*(\frac{n-i}{d}) \right ) i=1nF[i]diμ(d)(dni)

∑ i = 1 n F [ i ] ( ∑ d ∣ i μ ( d ) n d − ∑ d ∣ i μ ( d ) i d ) \sum_{i=1}^nF[i]\left ( \sum_{d|i}\mu(d)\frac{n}{d}-\sum_{d|i}\mu(d)\frac{i}{d}\right ) i=1nF[i]diμ(d)dndiμ(d)di

设 f ( i ) = ∑ d ∣ i μ ( d ) n d , ∑ d ∣ i μ ( d ) i d = φ , 得 : 设\blue{f(i)=\sum_{d|i}\mu(d)\frac{n}{d},\sum_{d|i}\mu(d)\frac{i}{d}=\varphi},得: f(i)=diμ(d)dndiμ(d)di=φ

∑ i = 1 n F [ i ] ∗ ( f ( i ) − φ ( i ) ) \sum_{i=1}^nF[i]*(f(i)-\varphi(i)) i=1nF[i](f(i)φ(i))

μ 、 φ 、 F 和 f 预 处 理 , 然 后 O ( n ) 得 答 案 。 \red{\mu、\varphi、F和f预处理,然后O(n)得答案。} μφFfO(n)

Code(20MS)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

// const ll mod = 998244353;
const ll mod = 1e9 + 7;
// const double eps = 1e-6;
// const double PI = acos(-1);
// const double R = 0.57721566490153286060651209;

const int N = 1e6 + 10;

int mu[N], f[N], phi[N];
int F[N];
bool is_prime[N];
int prime[N];
int cnt;

int n;

int Clac(int x) {
    int res = 0;
    while(x) {
        res += x % 10;
        x /= 10;
    }
    return res;
}

void Init() {
    mu[1] = 1;is_prime[0] = is_prime[1] = true;
    for(int i = 2;i < N; i++) {
        if (!is_prime[i]) {
            mu[i] = -1;
            phi[i] = i - 1;
            prime[++cnt] = i;
        }
        for (int j = 1; j <= cnt && i * prime[j] < N; j++) {
            is_prime[i * prime[j]] = true;
            if(i % prime[j]) {
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            }
            else {
                phi[i * prime[j]] = phi[i] * prime[j];
                mu[i * prime[j]] = 0;
                break;
            }
            mu[i * prime[j]] = -mu[i];
        }
    }
    for(int i = 1;i <= n; i++) {
        F[i] = Clac(i);
        for(int j = i;j <= n; j += i) {
            f[j] += mu[i] * (n / i);
        }
    }
}

void solve() {
    cin >> n;
    Init();
    ll ans = 0;
    for(int i = 1;i <= n; i++) {
        ans += 1ll * F[i] * (f[i] - phi[i]);
    }
    cout << ans << endl;
}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值