牛客练习赛76 F-phi and phi 莫比乌斯反演+差分

牛客练习赛76 F-phi and phi 莫比乌斯反演+差分


传送门: https://ac.nowcoder.com/acm/contest/10845/F

题意

求 解 a n s [ i ] = ∑ i = 1 n ∑ j = 1 n φ ( i j ) φ [ g c d ( i , j ) ] 求解ans[i]=\sum_{i=1}^n\sum_{j=1}^n\varphi (ij)\varphi [gcd(i,j)] ans[i]=i=1nj=1nφ(ij)φ[gcd(i,j)]

思路

前 置 技 能 : φ ( i j ) = φ ( i ) φ ( j ) g c d ( i , j ) φ [ g c d ( i , j ) ] \red{前置技能:\varphi(ij)=\frac{\varphi(i) \varphi(j)gcd(i,j)}{\varphi[gcd(i,j)]}} φ(ij)=φ[gcd(i,j)]φ(i)φ(j)gcd(i,j)

根 据 上 式 得 : 根据上式得:
∑ i = 1 n ∑ j = 1 n φ ( i ) φ ( j ) g c d ( i , j ) \sum_{i=1}^n\sum_{j=1}^n\varphi (i)\varphi(j)gcd(i,j) i=1nj=1nφ(i)φ(j)gcd(i,j)

∑ k = 1 n k ∑ i = 1 n ∑ j = 1 n φ ( i ) φ ( j ) [ g c d ( i , j ) = k ] \sum_{k=1}^nk\sum_{i=1}^n\sum_{j=1}^n\varphi (i)\varphi(j)[gcd(i,j)=k] k=1nki=1nj=1nφ(i)φ(j)[gcd(i,j)=k]

∑ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ φ ( i k ) φ ( j k ) [ g c d ( i , j ) = 1 ] \sum_{k=1}^nk\sum_{i=1}^{\left \lfloor \frac{n}{k}\right \rfloor}\sum_{j=1}^{\left \lfloor \frac{n}{k}\right \rfloor}\varphi (ik)\varphi(jk)[gcd(i,j)=1] k=1nki=1knj=1knφ(ik)φ(jk)[gcd(i,j)=1]

∑ k = 1 n k ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ φ ( i k ) φ ( j k ) ∑ d ∣ i    d ∣ j μ ( d ) \sum_{k=1}^nk\sum_{i=1}^{\left \lfloor \frac{n}{k}\right \rfloor}\sum_{j=1}^{\left \lfloor \frac{n}{k}\right \rfloor}\varphi (ik)\varphi(jk)\sum_{d|i\;d|j}\mu(d) k=1nki=1knj=1knφ(ik)φ(jk)didjμ(d)

交 换 枚 举 顺 序 : 交换枚举顺序:

∑ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∑ i = 1 ⌊ n k d ⌋ ∑ j = 1 ⌊ n k d ⌋ φ ( i k d ) φ ( j k d ) \sum_{k=1}^nk\sum_{d=1}^{\left \lfloor \frac{n}{k}\right \rfloor}\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{kd}\right \rfloor}\sum_{j=1}^{\left \lfloor \frac{n}{kd}\right \rfloor}\varphi (ikd)\varphi(jkd) k=1nkd=1knμ(d)i=1kdnj=1kdnφ(ikd)φ(jkd)

∑ k = 1 n k ∑ d = 1 ⌊ n k ⌋ μ ( d ) [ ∑ j = 1 ⌊ n k d ⌋ φ ( i k d ) ] 2 \sum_{k=1}^nk\sum_{d=1}^{\left \lfloor \frac{n}{k}\right \rfloor}\mu(d)[\sum_{j=1}^{\left \lfloor \frac{n}{kd}\right \rfloor}\varphi (ikd)]^2 k=1nkd=1knμ(d)[j=1kdnφ(ikd)]2

令 T = k d 并 交 换 枚 举 顺 序 : 令T=kd并交换枚举顺序: T=kd

∑ T = 1 n ∑ k ∣ T k μ ( T k ) [ ∑ j = 1 ⌊ n T ⌋ φ ( i T ) ] 2 \sum_{T=1}^{n}\sum_{k|T}k\mu(\frac{T}{k})[\sum_{j=1}^{\left \lfloor \frac{n}{T}\right \rfloor}\varphi (iT)]^2 T=1nkTkμ(kT)[j=1Tnφ(iT)]2

由 φ = i d ∗ μ 得 : 由\varphi = id*\mu得: φ=idμ

∑ T = 1 n φ ( T ) [ ∑ j = 1 ⌊ n T ⌋ φ ( i T ) ] 2 \sum_{T=1}^{n}\varphi(T)[\sum_{j=1}^{\left \lfloor \frac{n}{T}\right \rfloor}\varphi (iT)]^2 T=1nφ(T)[j=1Tnφ(iT)]2

设 f ( n / T ) = ∑ j = 1 ⌊ n T ⌋ φ ( i T ) , 则 最 终 式 为 : 设f(n/T)=\sum_{j=1}^{\left \lfloor \frac{n}{T}\right \rfloor}\varphi (iT),则最终式为: f(n/T)=j=1Tnφ(iT)

a n s [ n ] = ∑ T = 1 n φ ( T ) [ f ( n / T ) ] 2 ans[n]=\sum_{T=1}^n\varphi(T)[f(n/T)]^2 ans[n]=T=1nφ(T)[f(n/T)]2

但 是 这 题 要 求 的 是 a n s [ 1 − n ] , 我 们 发 现 但是这题要求的是ans[1 - n],我们发现 ans[1n]

在 枚 举 T 时 , n 在 [ i ∗ T , ( i + 1 ) ∗ T ) 之 间 , n T 的 值 都 一 样 , φ ( T ) [ f ( n / T ) ] 2 的 贡 献 不 变 。 在枚举T时,n在[i*T,(i+1)*T)之间,\frac{n}{T}的值都一样,\varphi(T)[f(n/T)]^2的贡献不变。 Tn[iT,(i+1)T),Tnφ(T)[f(n/T)]2

所 以 我 们 在 求 a n s [ n ] 的 过 程 中 , 对 i ∗ T 做 一 个 差 分 , 最 后 在 求 一 个 前 缀 和 即 可 。 所以我们在求ans[n]的过程中,对i*T做一个差分,最后在求一个前缀和即可。 ans[n]iT

Code(445MS)

#pragma GCC optimize(2)
#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 vis[N * 3], prime[N * 3], num;
ll phi[N * 3], ans[N * 3];

void init() {
    phi[1] = 1; num = 0;
    for (int i = 2; i < N; i++) {
        if (!vis[i]) {
            prime[++num] = i; phi[i] = i - 1;
        }
        for (int j = 1; j <= num && i * prime[j] < N; j++) {
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            else phi[i * prime[j]] = phi[i] * phi[prime[j]];
        }
    }
}

void solve() {
    init();
    int n; scanf("%d",&n);
    for(int T = 1;T <= n; T++) {
        ll sum = 0;
        for(int i = 1;i <= n / T; i++) {
            sum = (sum + phi[i * T]) % mod;
            ans[i * T] = (ans[i * T] + phi[T] * sum % mod * sum % mod + mod) % mod;
            ans[(i + 1) * T] = (ans[(i + 1) * T] - phi[T] * sum % mod * sum % mod + mod) % mod;
        }
    }
    for(int i = 1;i <= n; i++) {
        ans[i] = ((ans[i] + ans[i - 1]) % mod + mod) % mod;
        printf("%lld\n",ans[i]);
    }
    // cout << endl;
}

signed main() {
    solve();
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值