洛谷P2257 YY的GCD

题目描述

神犇YY虐完数论后给傻×kAc出了一题

给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对

kAc这种傻×必然不会了,于是向你来请教……

多组输入

输入输出格式

输入格式:

第一行一个整数T 表述数据组数

接下来T行,每行两个正整数,表示N, M

输出格式:

T行,每行一个整数表示第i组数据的结果

输入输出样例

输入样例#1: 复制

2
10 10
100 100

输出样例#1: 复制

30
2791

说明

T = 10000

N, M <= 10000000

题意:略。

分析:莫比乌斯反演套路。

f[n]=gcd==x的个数

F[n]=gcd==x与x的倍数的个数

接下来推公式。

F(n)=\sum _{n|d}f(d)= (N/n)*(M/n)

f(n)=\sum _{n|d}u(d/n)*F(d)

ans=\sum _{p\sqsubseteq prim}f(p)=\sum _{p\sqsubseteq prim}\sum _{p|d}u(d/p)*(N/d)*(M/d)

令t=d/p

ans=\sum _{p\sqsubseteq prim}\sum _{t=1}^{min(N/p,M/p)}u(t)*(N/tp)*(M/tp)

令T=tp

ans=\sum _{p\sqsubseteq prim}\sum _{T=1}^{min(N,M)}u(T/P)*(N/T)*(M/T)

ans=\sum _{T=1}^{min(N,M)}\sum _{p\sqsubseteq prim,p|T}u(T/P)*(N/T)*(M/T)

ans=\sum _{T=1}^{min(N,M)}(N/T)*(M/T)\sum _{p\sqsubseteq prim,p|T}u(T/P)

前面部分分块求,后面部分前缀和处理。

#include<bits/stdc++.h>


using namespace std;
long long mu[10000004];
long long prim[10000004];
bool vis[10000004];
int cnt = 0;
long long g[10000004];
long long pre[10000004];

void init() {
    memset(prim, 0, sizeof(prim));
    memset(mu, 0, sizeof(mu));
    memset(vis, 0, sizeof(vis));
    mu[1] = 1;
    for (int i = 2; i < 10000004; ++i) {
        if (!vis[i]) {
            prim[cnt++] = i;
            mu[i] = -1;
        }
        for (int j = 0; j < cnt && i * prim[j] < 10000004; ++j) {
            vis[i * prim[j]] = 1;
            if (i % prim[j] == 0)break;
            else mu[i * prim[j]] = -mu[i];
        }
    }
    for (int i = 0; i < cnt; ++i) {
        for (int j = 1; j * prim[i] < 10000004; ++j) {
            g[j * prim[i]] += mu[j];
        }
    }
    for (int i = 1; i < 10000004; ++i) {
        pre[i] = pre[i - 1] + g[i];
    }
}


int main() {
    init();
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, m;
        scanf("%d%d", &n, &m);
        long long ans = 0;
        int l, r;
        if (n > m)swap(n, m);
        for (l = 1; l <= n; l = r + 1) {
            r = min(n / (n / l), m / (m / l));
            ans += (long long) (n / l) * (m / l) * (pre[r] - pre[l - 1]);
        }
        printf("%lld\n", ans);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42671946/article/details/89190470