牛客挑战赛47 F-简单题 莫比乌斯反演

牛客挑战赛47 F-简单题 莫比乌斯反演

    • 题意
    • 思路
    • Code(2512 MS)

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

题意

求 解 ∑ i = 1 n ∑ j = 1 m g c d ( i , j ) μ ( i j ) φ ( i j ) 求解\sum_{i=1}^n\sum_{j=1}^mgcd(i,j)\mu(ij)\varphi (ij) i=1nj=1mgcd(i,j)μ(ij)φ(ij)

思路

根 据 积 性 函 数 和 μ 的 性 质 , 只 有 i 和 j 互 质 时 才 有 贡 献 , 不 然 μ ( i j ) = 0 \red{根据积性函数和\mu的性质,只有i和j互质时才有贡献,不然\mu(ij)=0} μijμ(ij)=0
i 和 j 互 质 时 , φ ( i j ) = φ ( i ) φ ( j )      μ ( i j ) = μ ( i ) μ ( j )      g c d ( i , j ) = 1 \red{i和j互质时,\varphi (ij)=\varphi (i)\varphi (j)\;\;\mu(ij)=\mu(i)\mu(j)\;\;gcd(i,j)=1} ijφ(ij)=φ(i)φ(j)μ(ij)=μ(i)μ(j)gcd(i,j)=1

根 据 上 述 可 得 : 根据上述可得:

∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] φ ( i ) μ ( i ) φ ( j ) μ ( j ) \sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=1]\varphi (i)\mu(i)\varphi (j)\mu(j) i=1nj=1m[gcd(i,j)=1]φ(i)μ(i)φ(j)μ(j)
设 f ( i ) = φ ( i ) ∗ μ ( i ) , g ( j ) = φ ( j ) ∗ μ ( j ) , 则 设f(i)=\varphi (i)*\mu(i),g(j)=\varphi (j)*\mu(j),则 f(i)=φ(i)μ(i)g(j)=φ(j)μ(j)

∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] f ( i ) g ( j ) \sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=1]f(i)g(j) i=1nj=1m[gcd(i,j)=1]f(i)g(j)

∑ i = 1 n ∑ j = 1 m f ( i ) g ( j ) ∑ d ∣ i    d ∣ j μ ( d ) \sum_{i=1}^n\sum_{j=1}^mf(i)g(j)\sum_{d|i\;d|j}\mu(d) i=1nj=1mf(i)g(j)didjμ(d)

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

∑ d = 1 m i n ( n , m ) μ ( d ) ∑ i = 1 n f ( i ) [ d ∣ i ] ∑ j = 1 m g ( j ) [ d ∣ j ] \sum_{d=1}^{min(n,m)}\mu(d)\sum_{i=1}^nf(i)[d|i]\sum_{j=1}^mg(j)[d|j] d=1min(n,m)μ(d)i=1nf(i)[di]j=1mg(j)[dj]

根 据 上 式 , 可 以 预 处 理 φ , μ , f , g 函 数 。 然 后 暴 力 求 解 , 即 : 根据上式,可以预处理\varphi,\mu,f,g函数。然后暴力求解,即: φ,μ,f,g

		int n, m; cin >> n >> m;
        for(int i = 1;i <= n; i++) f[i] = phi[i];
        for(int j = 1;j <= m; j++) g[j] = phi[j];
        ll ans = 0;

        for(int d = 1;d <= min(n, m); d++) {
            if(!mu[d]) continue;
            ll sum1 = 0, sum2 = 0;
            for(int i = d;i <= n; i += d) sum1 += f[i];
            for(int j = d;j <= m; j += d) sum2 += g[j];
            ans = (ans + sum1 * sum2 * mu[d]) ;
        }

但 是 这 样 会 T 掉 , 因 为 d = 1 时 , n 过 大 , 那 复 杂 度 就 是 O ( n 2 ) 了 。 但是这样会T掉,因为d=1时,n过大,那复杂度就是O(n^2)了。 Td=1nO(n2)

需 要 D i r i c h l e t 前 缀 和 优 化 即 可 。 这 是 前 缀 和 的 几 个 版 本 : 需要Dirichlet 前缀和优化即可。这是前缀和的几个版本: DirichletDirichlet 前缀和

D i r i c h l e t 前 缀 和 优 化 之 后 的 复 杂 度 为 O ( n log ⁡ log ⁡ n ) , 完 全 可 以 接 受 。 Dirichlet 前缀和优化之后的复杂度为O(n\log \log n),完全可以接受。 DirichletO(nloglogn)

Code(2512 MS)

#include 

using namespace std;

typedef long long ll;

const ll mod = (1ll << 32);
const int N = 2e7 + 10;

int cnt;
int prime[N];
bool is_prime[N];
int mu[N];
int phi[N];

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

    for(int i = 1;i < N; i++) phi[i] *= mu[i];

}

int f[N], g[N];

void solve() {
    int _; cin >> _;
    init();
    while(_--) {
        int n, m; cin >> n >> m;
        for(int i = 1;i <= n; i++) f[i] = phi[i];
        for(int j = 1;j <= m; j++) g[j] = phi[j];
        
        ll ans = 0;
        
        for(int i = 1;i <= cnt; i++) {
            for(int j = n / prime[i];j >= 1; j--) f[j] += f[j * prime[i]];
            for(int j = m / prime[i];j >= 1; j--) g[j] += g[j * prime[i]];
        }

        for(int i = 1;i <= min(n, m); i++) {
            ans += 1ll * f[i] * g[i] * mu[i] % mod;
            ans %= mod;
        }
        cout << (ans + mod) % mod << endl;
    }
}

signed main() {
    solve();
    return 0;
}

你可能感兴趣的:(莫比乌斯反演)