BZOJ 4916 [莫比乌斯反演][杜教筛]

Description

i=1Nμ(i2)
以及
i=1Nφ(i2)

Solution

第一问puts("1");
第二问考虑杜教筛,首先发现式子求的就是

S(N)=i=1Nφ(i)i
我们令
f(x)=φ(i)i
发现
(fid)(n)=d|nφ(d)dnd=d|nφ(d)n
构造卷积,得
S(n)=i=1nid|iφ(d)i=2niS(ni)
整理,得
S(n)=n(n+1)(2n+1)6i=2nS(ni)i
这个东西就可以杜教筛啦。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <tr1/unordered_map>
using namespace std;
using namespace tr1;

const int MOD = 1000000007;
const int N = 1000100;
const int INV = 166666668;
typedef long long ll;

int n, Pcnt, x, ans, res, tmp, pos;
int prime[N], phi[N], vis[N];
unordered_map<int, int> PHI;

inline void inc(int &x, int a) {
    x += a;
    while (x >= MOD) x -= MOD;
}
inline void dec(int &x, int a) {
    x -= a;
    while (x < 0) x += MOD;
}

int Phi(int x) {
    if (x < N) return phi[x];
    if (PHI.count(x)) return PHI[x];
    int p = (ll)x * (x + 1) % MOD * (x * 2 + 1) % MOD * INV % MOD, pos, res;
    for (int i = 2; i <= x; i = pos + 1) {
        pos = x / (x / i);
        res = (ll)(i + pos) * (pos - i + 1) / 2 % MOD * Phi(x / i) % MOD;
        dec(p, res);
    }
    return PHI[x] = p;
}

int main(void) {
    puts("1"); scanf("%d", &n);
    for (int i = 2; i < N; i++) {
        if (!vis[i]) {
            prime[++Pcnt] = i;
            phi[i] = i - 1;
        }
        for (int j = 1; j <= Pcnt && (x = prime[j] * i) < N; j++) {
            vis[x] = 1;
            if (i % prime[j]) {
                phi[x] = phi[i] * phi[prime[j]];
            } else {
                phi[x] = phi[i] * prime[j];
                break;
            }
        }
    }
    phi[1] = 1;
    for (int i = 2; i < N; i++) {
        phi[i] = (ll)phi[i] * i % MOD;
        inc(phi[i], phi[i - 1]);
    }
    printf("%d\n", Phi(n));
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值