洛谷【P2257】YY的GCD

YY的GCD

原题链接

这应该是我做的第一道莫比乌斯反演的题目。

题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

说明

  • T=10000,N, M <= 10000000

解题思路

  • 显然,题目要求的$Ans$实际上就是$\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(x,y)=prim]$的值
  • 接下来,我们就开始进行欢乐的推式子
  • 对于这种与$gcd$有关的莫比乌斯反演,一般我们都是套路的去设$f(d)$为$gcd(i,j)=d$的个数,$F(n)$为$gcd(i,j)=d$和$d$的倍数的个数,即:
    $$f(d)=\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=d]$$
    $$F(n)=\sum_{n|d}f(d)=\lfloor\frac{N}{n}\rfloor\lfloor\frac{M}{n}\rfloor$$
    $$f(n)=\sum_{n|d}\mu(\lfloor\frac{d}{n}\rfloor)F(d)$$
  • 这样,我们便可以开心的化简这个式子了!
    $$Ans=\sum_{p\in prim}\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=p]$$
    将$f(p)$带入得:
    $$Ans=\sum_{p\in prim}f(p)$$
    然后就莫比乌斯反演一下
    $$Ans=\sum_{p\in prim}\sum_{p|d}\mu(\lfloor\frac{d}{p}\rfloor)F(d)$$
    我们换一个枚举项,我们枚举$\lfloor\frac{d}{p}\rfloor$
    $$Ans=\sum_{p\in prim}\sum_{d=1}^{min(n,m)}\mu(d)F(dp)=\sum_{p\in prim}\sum_{d=1}^{min(n,m)}\mu(d)\lfloor\frac{n}{dp}\rfloor\lfloor\frac{m}{dp}\rfloor$$
    这个$dp$一看就很不爽,于是我们把它换成$T$
    $$Ans=\sum_{T=1}^{min(n,m)}\sum_{t|T}\mu(\lfloor\frac{T}{t}\rfloor)\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor$$
    $$Ans=\sum_{T=1}^{min(n,m)}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor(\sum_{t|T}\mu(\lfloor\frac{T}{t}\rfloor))$$
    推到这里,我们就可以开始做了。如果是单组询问,我们就直接$O(n)$做。(不过好像一般这种题,都不会让你直接处理。)如果是多组数据的话,我们就只要在打一个简单的整除分块就可以了。后面的$\mu$函数可以线筛出来。由于整除分块的缘故,我们就只需要记一个前缀和就可以了。
  • 下面贴一个完整的代码吧。
#include<bits/stdc++.h>
#define N 10000100
using namespace std;
inline void read(int &x)
{
    x=0;
    static int p;p=1;
    static char c;c=getchar();
    while(!isdigit(c)){if(c=='-')p=-1;c=getchar();}
    while(isdigit(c)) {x=(x<<1)+(x<<3)+(c-48);c=getchar();}
    x*=p;
}
inline void print(long long x)
{
    static int cnt;
    static int a[15];
    cnt=0;
    do
    {
        a[++cnt]=x%10;
        x/=10;
    }while(x);
    for(int i=cnt;i>=1;i--)putchar(a[i]+'0');
    puts("");
}
bool vis[N];
long long mu[N],sum[N],g[N],prim[N];
int cnt;
void get_mu(int n)
{
    mu[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!vis[i]){mu[i]=-1;prim[++cnt]=i;}
        for(int j=1;j<=cnt&&prim[j]*i<=n;j++)
        {
            vis[i*prim[j]]=1;
            if(i%prim[j]==0)break;
            else mu[prim[j]*i]=-mu[i];
        }
    }
    for(int j=1;j<=cnt;j++)
        for(int i=1;i*prim[j]<=n;i++)g[i*prim[j]]+=mu[i];
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+g[i];
}
int n,m;
int main()
{
#ifndef ONLINE_JUDGE
    freopen("P2257.in","r",stdin);
    freopen("P2257.out","w",stdout);
#endif
    int t;
    read(t);
    get_mu(10000000);
    while(t--)
    {
        read(n);read(m);
        if(n>m)swap(n,m);
        static long long ans;ans=0;
        for(long long l=1,r;l<=n;l=r+1)
        {
            r=min(n/(n/l),m/(m/l));
            ans+=(n/l)*(m/l)*(sum[r]-sum[l-1]);
        }
        print(ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/peng-ym/p/8652288.html

时间: 2024-08-30 16:38:43

洛谷【P2257】YY的GCD的相关文章

P2257 YY的GCD

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

P2257 YY的GCD(莫比乌斯反演)

P2257 YY的GCD luogu题解第一篇非常棒,当然你也可以point here(转) 正题因为题解写的太优秀所以没得补充 这里用了一个卡常技巧:循环展开 就是以代码长度为代价减少循环次数 实测快了15ms(一个点1.5ms....) (用了快读更慢???(大雾)但是register真有用) #include<iostream> #include<cstdio> #include<cstring> #include<cctype> #define re

P2257 YY的GCD (莫比乌斯反演)

[题目链接] https://www.luogu.org/problemnew/show/P2257 // luogu-judger-enable-o2 /* ----------------------- [题解] https://www.luogu.org/blog/peng-ym/solution-p2257 [莫比乌斯反演] http://www.cnblogs.com/peng-ym/p/8647856.html [整除分块] http://www.cnblogs.com/peng-y

P2257 YY的GCD (莫比乌斯反演)

题意:求\[\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j) = prim]\] 题解:那就开始化式子吧!! \[f(d) = \sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j) = d]\] \[F(x) = \sum_{d|x} f(d) = \left \lfloor \frac{n}{x} \right \rfloor \left \lfloor \frac{m}{x} \right \rfloor\] \[f(d) = \sum_{d|

[题解]luogu P2257 YY的GCD

袁野的gcd 首先可以肯定的是这是一道数论题 所以题目就是: \(\sum_{i=1}^N \sum_{j=1}^M [gcd(i,j)\in prime]\) 接下来就可以愉快的推式子了~ 首先可以按套路枚举 prime 和 gcd \(\sum_{p \in prime}\sum_{i=1}^N\sum_{j=1}^M[gcd(i,j)=p]\) 所以我们显然可以将\(i\)和\(j\) 同时除以 \(p\),得到 \(\sum_{p\in prime}\sum_{i=1}^{N}\sum_

luogu P2257 YY的GCD

嘟嘟嘟 感觉这几道数论题都差不多,但这到明显是前几道的升级版. 推了一大顿只能得60分,不得不看题解. 各位看这老哥的题解吧 我就是推到他用\(T\)换掉\(kd\)之前,然后枚举\(T\)的.这个转换确实想不出来啊. 还有最后一句,最终的式子 \[\sum_{T = 1} ^ {n} \lfloor \frac{n}{T} \rfloor \lfloor \frac{m}{T} \rfloor * \sum_{k | T} \mu(\frac{T}{k}) (k \in prime)\] 他把

【BZOJ2820】YY的GCD(莫比乌斯反演)

[BZOJ2820]YY的GCD(莫比乌斯反演) 题面 讨厌权限题!!!提供洛谷题面 题解 单次询问\(O(n)\)是做过的一模一样的题目 但是现在很显然不行了, 于是继续推 \[ans=\sum_{d=1}^n[d\_is\_prime]\sum_{i=1}^{n/d}[\frac{n}{id}][\frac{m}{id}]\] 老套路了 令\(T=id\) \[ans=\sum_{T=1}^{n}[\frac{n}{T}][\frac{m}{T}]\sum_{d|T}[d\_is\_prim

[题解]洛谷比赛『期末考后的休闲比赛2』

[前言] 这场比赛已经结束了有几天,但我各种忙,虽然AK但还是没来得及写题解.(我才不会告诉你我跑去学数据结构了) T1 区间方差 (就不贴题好了) 首先可以推公式(我们可以知道,线段树然而并不能通过初中学过的方差公式在log(L)内求出方差): (s2表示方差,L表示区间长度,xi表示区间的每一项,最后一个x上画了一根线表示这些数据的平均数) 用二项式定理完全平方公式可得: 再次展开: 另外,再代入以下这个 得到了: 然后继续吧.. 然后duang地一声合并同类项,于是我们得到了: 然后可以高

洛谷 P3227 BZOJ 3144 [HNOI2013]切糕

题目描述 经过千辛万苦小 A 得到了一块切糕,切糕的形状是长方体,小 A 打算拦腰将切糕切成两半分给小 B.出于美观考虑,小 A 希望切面能尽量光滑且和谐.于是她找到你,希望你能帮她找出最好的切割方案. 出于简便考虑,我们将切糕视作一个长 P.宽 Q.高 R 的长方体点阵.我们将位于第 z层中第 x 行.第 y 列上(1≤x≤P, 1≤y≤Q, 1≤z≤R)的点称为(x,y,z),它有一个非负的不和谐值 v(x,y,z).一个合法的切面满足以下两个条件: 与每个纵轴(一共有 P*Q 个纵轴)有且