2019年南昌邀请赛网络赛G:tsy's number 莫比乌斯反演

@[toc]

题意

比赛链接
补题链接
T(1e4),n(1e7),求\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n\frac{\phi(i)\phi(j^2)\phi(k^3)}{\phi(i)\phi(j)\phi(k)}\phi(gcd(i,j,k)),模2^{30}

思路

参考:walfy猝s在学ACM的路上hiarcher

因为:\phi(x)=x\times \prod_{p|x}\frac{p-1}p
所以:\phi(x^2)=\phi(x)\times x,\phi(x^3)=x^2\times \phi(x)
ans=\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^nj\times k^2\times \phi(gcd(i,j,k))
\sum_{d=1}^n\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^nj\times k^2\times \phi(d)[gcd(i,j,k)==d]
\sum_{d=1}^n\phi(d)\times d^3\sum_{i=1}^{\frac nd}\sum_{j=1}^{\frac nd}\sum_{k=1}^{\frac nd}j\times k^2\times[gcd(i,j,k)==1]
\sum_{d=1}^n\phi(d)\times d^3\sum_{i=1}^{\frac nd}\sum_{j=1}^{\frac nd}\sum_{k=1}^{\frac nd}j\times k^2\times\sum_{h|gcd(i,j,k)}\mu(h)
\sum_{d=1}^n\phi(d)\times d^3\sum_{h=1}^{\frac nd}\mu(h)\sum_{i=1}^{\frac n{dh}}\sum_{j=1}^{\frac n{dh}}\sum_{k=1}^{\frac n{dh}}j\times k^2\times h^3
\sum_{d=1}^n\phi(d)\sum_{h=1}^{\frac nd}\mu(h)\times (dh)^3[\frac n{dh}\times \frac{\frac n{dh}\times(\frac n{dh}+1)}2\times \frac{\frac n{dh}\times(\frac n{dh}+1)\times(2\times \frac n{dh}+1)}{2\times 3}]
T=dh
\sum_{T=1}^n\sum_{d|T}\phi(d)\times \mu(\frac Td)\times T^3\times [\frac n{T}\times \frac{\frac n{T}\times(\frac n{T}+1)}2\times \frac{\frac n{T}\times(\frac n{T}+1)\times(2\times \frac n{T}+1)}{2\times 3}]


现在问题变成了O(n)求出g(n)=\sum_{d|n}\phi(d)\mu(\frac nd),显然这是一个积性函数。
积性函数就是对所有互质的a,b满足f(ab)=f(a)f(b)的数论函数。
为了能欧拉筛的同时筛出g(n),我们先试着推出g(p^k)

g(p)=\phi(p)\mu(1)+\phi(1)\mu(p)=p-2
k!=1:g(p^k)=\sum_{i=0}^k\phi(p^i)\mu(p^{k-i})=\phi(p^k)\mu(1)+\phi(p^{k-1})\mu(p)=\phi(p^k)-\phi(p^{k-1})
=p^k-p^{k-1}-(p^{k-1}-p^{k-2})=p^{k-2}\times(p-1)^2
k\ge3时,g(p^k)=g(p^{k-1})\times p

为了线性筛出g(n),还需要记录num(n)表示n的最小质因子的幂。
代码如下:

void init_prime() {
    noprime[0] = noprime[1] = 1;
    mu[1] = 1; phi[1] = 1;g[1] = num[1] = 1;
    for(int i = 2, ret; i < MXN; ++i) {
        if(!noprime[i]) pp[pcnt++] = i, phi[i] = i-1, mu[i] = -1, g[i]=i-2, num[i]=1;
        for(int j = 0; j < pcnt && pp[j] * i < MXN; ++j) {
            ret = i * pp[j];
            noprime[ret] = 1;
            phi[ret] = (pp[j]-1)*phi[i];
            mu[ret] = -mu[i];
            g[ret] = g[i]*g[pp[j]];
            num[ret] = 1;
            if(i % pp[j] == 0) {
                phi[ret] = pp[j]*phi[i];
                mu[ret] = 0;
                num[ret] = num[i] + 1;
                if(num[i] == 1) {
                    if(pp[j] == 2) g[ret] = g[i/pp[j]];
                    else g[ret] = g[i]/(pp[j]-2)*(pp[j]-1)*(pp[j]-1);
                }else g[ret] = g[i] * pp[j];
                break;
            }
        }
    }
    for(int i = 1; i < MXN; ++j) {
        g[i] = g[i-1] + (LL)i * i % mod * i % mod;
        if(g[i] >= mod) g[i] %= mod;
    }
}

对了模数是2^{30},结果的式子里面有除2和除3,除2的话用long long直接算就行,3的逆元用欧拉定理算出来是:715827883。

AC_CODE

#pragma comment(linker, "/STACK:102400000,102400000")
#include <bits/stdc++.h>
#include <ctime>
#include <iostream>
#include <assert.h>
#include <vector>
#include <queue>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define fi first
#define se second
#define endl '\n'
#define o2(x) (x)*(x)
#define BASE_MAX 31
#define mk make_pair
#define eb push_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define clr(a, b) memset((a),(b),sizeof((a)))
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
#define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> pii;
inline LL read() {
    LL x = 0;int f = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x = f ? -x : x;
}
inline void write(LL x, bool f) {
    if (x == 0) {putchar('0'); if(f)putchar('\n');else putchar(' ');return;}
    if (x < 0) {putchar('-');x = -x;}
    static char s[23];
    int l = 0;
    while (x != 0)s[l++] = x % 10 + 48, x /= 10;
    while (l)putchar(s[--l]);
    if(f)putchar('\n');else putchar(' ');
}
int lowbit(int x) { return x & (-x); }
template<class T>T big(const T &a1, const T &a2) { return a1 > a2 ? a1 : a2; }
template<class T>T sml(const T &a1, const T &a2) { return a1 < a2 ? a1 : a2; }
template<typename T, typename ...R>T big(const T &f, const R &...r) { return big(f, big(r...)); }
template<typename T, typename ...R>T sml(const T &f, const R &...r) { return sml(f, sml(r...)); }
void debug_out() { cerr << '\n'; }
template<typename T, typename ...R>void debug_out(const T &f, const R &...r) {cerr << f << " ";debug_out(r...);}
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
 
 
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int HMOD[] = {1000000009, 1004535809};
const LL BASE[] = {1572872831, 1971536491};
const int mod = 1 << 30;//715827883
const int MOD = 1e9 + 7;//998244353
const int INF = 0x3f3f3f3f;
const int MXN = 1e7 + 7;
const int MXE = 2e6 + 7;
int n, m;
bool noprime[MXN];
int pp[MXN], pcnt;
int num[MXN];
LL g[MXN], inv = 715827883;

void init_prime() {
    noprime[0] = noprime[1] = 1;
    g[1] = num[1] = 1;
    for(int i = 2, ret; i < MXN; ++i) {
        if(!noprime[i]) pp[pcnt++] = i, g[i]=i-2, num[i]=1;
        for(int j = 0; j < pcnt && pp[j] * i < MXN; ++j) {
            ret = i * pp[j];
            noprime[ret] = 1;
            g[ret] = g[i]*g[pp[j]];
            num[ret] = 1;
            if(i % pp[j] == 0) {
                num[ret] = num[i] + 1;
                if(num[i] == 1) {
                    if(pp[j] == 2) g[ret] = g[i/pp[j]];
                    else g[ret] = g[i]/(pp[j]-2)*(pp[j]-1)*(pp[j]-1);
                }else g[ret] = g[i] * pp[j];
                break;
            }
        }
    }
    for(int i = 1; i < MXN; ++i) {
        g[i] = g[i-1] + g[i] * i * i % mod * i % mod;
        if(g[i] >= mod) g[i] %= mod;
    }
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("E://ADpan//in.in", "r", stdin);
    // freopen("E://ADpan//out.out", "w", stdout);
#endif
    init_prime();
    int tim = read();
    while(tim --) {
        n = read();
        LL ans = 0, tmp, ti, ret;
        for(int L = 1, R; L <= n; L = R + 1) {
            ti = n / L;
            R = n / ti;
            ret = (ti*(ti+1)/2)%mod;
            tmp = ti*ret%mod*(ret*(2*ti+1)%mod) % mod * inv % mod;
            ans = (ans + tmp * (g[R] - g[L-1]) % mod) % mod;
        }
        printf("%lld\n", (ans+mod)%mod);
    }
#ifndef ONLINE_JUDGE
    cout << "time cost:" << 1.0 * clock() / CLOCKS_PER_SEC << "ms" << endl;
#endif
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容