[BZOJ2820]YY的GCD

Posted Elder_Giang

tags:

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

2820: YY的GCD

Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 2248  Solved: 1207 [Submit][Status][Discuss]

Description

神犇YY虐完数论后给傻×kAc出了一题给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对kAc这种
傻×必然不会了,于是向你来请教……多组输入

Input

第一行一个整数T 表述数据组数接下来T行,每行两个正整数,表示N, M

Output

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

Sample Input

2
10 10
100 100

Sample Output

30
2791

HINT

T = 10000
N, M <= 10000000

 

由对称性,不妨设$n\\le m$

那么$ans=\\sum_{\\left(p\\right)IsPrime}\\sum_{i=1}^n\\sum_{j=1}^m\\left[gcd\\left(i,j\\right)=p\\right]$

由其它一些经典的题目(比如[POI2007]ZAP)很轻易地可以得到

$ans=\\sum_{\\left(p\\right)IsPrime}\\sum_{d=1}^{\\lfloor\\frac{n}{p}\\rfloor}\\mu\\left(d\\right)\\lfloor\\frac{n}{pd}\\rfloor\\lfloor\\frac{m}{pd}\\rfloor$

由于在前$n$个数中质数的个数约为$\\frac{n}{lnn}$个

那么即使是加上了分块优化时间复杂度也是$O\\left(\\frac{n\\sqrt{n}}{lnn}\\right)$肯定会TLE

考虑设$pd=T$

那么$ans=\\sum_{T=1}^{n}\\lfloor\\frac{n}{T}\\rfloor\\lfloor\\frac{m}{T}\\rfloor\\sum_{p\\mid T}\\mu\\left(\\frac{T}{p}\\right)$

那么加上分块优化和前缀和处理后单次询问的时间复杂度就是$O\\left(\\sqrt{n}\\right)$

总时间复杂度$O\\left(T\\sqrt{n}\\right)$

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 10000000 + 10;
bool mark[maxn] = {0};
int pri[664580], prn = 0;
int mu[maxn], sum[maxn];
void shai(){
    mu[1] = 1;
    for(int i = 2; i < maxn; i++){
        if(!mark[i]){
            mu[i] = -1;
            pri[++prn] = i;
        }
        for(int j = 1; j <= prn && i * pri[j] < maxn; j++){
            mark[i * pri[j]] = true;
            if(i % pri[j] == 0){
                mu[i * pri[j]] = 0;
                break;
            }
            else mu[i * pri[j]] = -mu[i]; // = mu[pri[j]] * mu[i]
        }
    }
    for(int i = 1; i <= prn; i++)
        for(int j = 1; j * pri[i] < maxn; j++) sum[pri[i] * j] += mu[j];
    sum[0] = 0;
    for(int i = 1; i < maxn; i++)
        sum[i] += sum[i - 1];
}
int main(){
    shai();
    int T, n, m;
    ll ans;
    scanf("%d", &T);
    while(T--){
        scanf("%d %d", &n, &m);    
        if(n > m) swap(n, m);
        ans = 0;
        for(int p, i = 1; i <= n; i = p + 1){
            p = min(n / (n / i), m / (m / i));
            ans += (ll) (sum[p] - sum[i - 1]) * (n / p) * (m / p);
        }
        printf("%lld\\n", ans);
    }
    return 0;
}

 

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

[BZOJ2820]YY的GCD

[BZOJ 2820]YY的GCD

bzoj 2820: YY的GCD

[BZOJ2820]YY的GCD

Bzoj 2820: YY的GCD

bzoj2820 YY的GCD