Bzoj 2820: YY的GCD

Posted gzygzy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj 2820: YY的GCD相关的知识,希望对你有一定的参考价值。

Bzoj 2820: YY的GCD

膜一发rqy
真正的学习了莫比乌斯反演后,感觉与以前做题完全不同了(飞升的感觉
居中的式子是大体思路
题目让我们求
$$sum_{i=1}^nsum_{j=1}^mgcd(i , j) == p$$
显然有一个结论$d | gcd(i,j) ? d | i , d | j$
我们继续推
$f(i)表示i是不是质数,如果是的话,f(i) = 1,不是f(i) = 0$
$$sum_{i=1}^nsum_{i=1}^mf(gcd(i,j))$$
反演$$f(n) = sum_{d|n}^ng(d)$$
就有$g(n) = sum_{d|n}f(d)mu (dfrac{n}{d})$
$g(n) = sum_{pmid n}muleft(frac np ight)(p为质数)$
$$sum_{i=1}^nsum_{i=1}^msum_{d|gcd(i,j)}g(d)$$
根据结论:
$$sum_{i=1}^nsum_{j=1}^msum_{d|i,d|j}g(d)$$
换个枚举点
$$sum_{d=1}^{min(n,m)}g(d)sum_{i=1}^nsum_{j=1}^m{[d|i][d|j]}$$
$$sum_{d=1}^{min(n,m)}g(d)[dfrac{n}{d}][dfrac{m}{d}]$$
推完了
用整除分块做
前面的式子可以用前缀和维护.

// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#define rep(i , x, p) for(register int i = x;i <= p;++ i)
#define sep(i , x, p) for(register int i = x;i >= p;-- i)
#define gc getchar()
#define pc putchar
#define ll long long
using std::max;
using std::swap;
const int maxN = 1e7 + 7;
const int N = 10000000;

inline int gi() {register int x = 0,f = 1;char c = gc;while(c < ‘0‘ || c > ‘9‘) {if(c == ‘-‘)f = -1;c = gc;}while(c >= ‘0‘ && c <= ‘9‘) {x = x * 10 + c - ‘0‘;c = gc;}return x * f;}
void print(ll x) {if(x < 0) pc(‘-‘) , x = -x;if(x >= 10) print(x / 10);pc(x % 10 + ‘0‘);}

inline int min(int a , int b) {return a > b ? b : a;}

int mu[maxN] , g[maxN], prime[maxN], num;
bool vis[maxN];

void init() {
    mu[1] = 1;
    rep(i , 2, N) {
        if(!vis[i]) {prime[++ num] = i;mu[i] = -1;}
        for(register int j = 1;j <= num && i * prime[j] <= N;++ j) {
            vis[i * prime[j]] = true;
            if(i % prime[j] == 0) break;
            mu[i * prime[j]] -= mu[i];
        }
    }
    rep(i , 1, num) {
        for(register int p = prime[i] , j = 1;j * p <= N;++ j) 
            g[j * p] += mu[j];
    }
    rep(j , 1, N) g[j] += g[j - 1];
}

inline ll work(int n , int m) {
    ll sum = 0;
    int tmp = min(n , m);
    for(register int l = 1 , r;l <= tmp;l = r + 1){
        r = min(n / (n / l) , m / (m / l));
        sum += (ll)(n / l) * (m / l) * (g[r] - g[l - 1]) ;
    }
    return sum;
}

int main() {
    init();
    int T = gi();
    while(T --) {
        int n = gi() , m = gi();
        print(work(n , m));pc(‘
‘);
    }
    return 0;
}




















以上是关于Bzoj 2820: YY的GCD的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ2820]YY的GCD

[BZOJ 2820]YY的GCD

bzoj 2820: YY的GCD

[BZOJ2820]YY的GCD

Bzoj 2820: YY的GCD

bzoj2820 YY的GCD