传送门

题目描述

神犇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

-----------------------------------------------------------------

这是我做得第一道莫比乌斯反演的题

虽然已经掌握了

莫比乌斯反演的证明

但是

显然这还差很多

因为

我不会应用到实际推演当中

当我再次弄懂该如何推演的时候

我自认为可以写出来的

但是

并没有

我发现我在很多细节上

还是很拿不准的

于是

再次卑微

----------------------------------------------------

解题思路:

如何实现前缀和呢??

这里就用到了整除分块(这也是这道题困扰我很久很久时间的部分)

那么什么是整除分块呢??

整除分块————一个莫比乌斯反演的题基本都会涉及到的小知识点,其实,是很有必要使之成为前置知识点中的其中之一

  • 可以用到整除分块的形式,大致是这样的:

    ∑i=1n⌊n/i⌋
  • 这个式子,O(n)计算是非常显然的。但,有的时候因为多组数据的要求,可能O(n)并不是正确的时间复杂度。那么这个时候,我们就有一种O(√n)

    的做法。这就是:整除分块

  • 对于每一个⌊n/i⌋

    我们可以通过打表(或理性的证明)可以发现:有许多⌊ni⌋

    的值是一样的,而且它们呈一个块状分布;再通过打表之类的各种方法,我们惊喜的发现对于每一个值相同的块,它的最后一个数就是n/(n/i)

    。得出这个结论后,我们就可以做的O(√n)

    处理了。

整除分块的代码如下:

for(int l=,r;l<=n;l=r+)
{
r=n/(n/l);
ans+=(r-l+)*(n/l);
}

那么现在我终于理解本题的代码了

#include<bits/stdc++.h>
#define N 10000100
using namespace std; inline void read(int &x)
{
x=;
static int p;p=;
static char c;c=getchar();
while(!isdigit(c)){if(c=='-')p=-;c=getchar();}
while(isdigit(c)) {x=(x<<)+(x<<)+(c-);c=getchar();}
x*=p;
} inline void print(long long x)
{
static int cnt;
static int a[];
cnt=;
do
{
a[++cnt]=x%;
x/=;
}
while(x);
for(int i=cnt;i>=;i--)
putchar(a[i]+'');
puts("");
} bool vis[N];//判断是否为素数
long long sum[N];
int prim[N];//存素数
int mu[N],g[N];//mu存μ
int cnt;//素数个数(筛素数用的,不用管啊)
void get_mu(int n)
{
mu[]=;
for(int i=;i<=n;i++)//线性筛??
{
if(!vis[i])//没有被访问过,即为素数
{
mu[i]=-;//素数的质因数只可能是它自己,所以,他的μ值一定为-1
prim[++cnt]=i;//prim数组是用来记录素数的 ,cnt累计素数个数
}
for(int j=;j<=cnt&&prim[j]*i<=n;j++)//和欧拉筛很像吧,就是用欧拉筛的思路的
//j是用来枚举素数的 ,prim[j]*i是筛合数,并保证筛掉的合数在应求的范围内(没有越界,没有浪费时间和空间)
{
vis[i*prim[j]]=;//打标记:筛掉合数
if(i%prim[j]==)//当前的数可以被质数整除的话 (在下一行)
break;//那么i%prim[j]的质因数中有两个相同的,也就是说i%prim[j]的μ值是0,(数组开的全局变量,默认初始值为0,所以就可以不用管它)
else
mu[prim[j]*i]=-mu[i];//不能被整除 i和prim[j]互质,得到的合数的 μ值为i的μ值的相反数
}
}
for(int j=;j<=cnt;j++)//如果把最终得到的公式看作是两层循环的话,那么这里相当于最里面的那层循环,也就是最右面的Σ
for(int d=;d*prim[j]<=n;d++)
g[d*prim[j]]+=mu[d]; //μ值累加
for(int i=;i<=n;i++)//而这个相当于最外面的循环,即最左面的Σ
{
sum[i]=sum[i-]+(long long)g[i];//据说这里是用来计算前缀和的??! !!我大概明白了!!!
}
}
int n,m;
int main()
{
int t;
read(t);
get_mu();
while(t--)
{
read(n);read(m);
if(n>m)swap(n,m);
static long long ans;
ans=;
for(int T=,d;T<=n;T=d+)
{
d=min(n/(n/T),m/(m/T));
ans+=1ll*(n/T)*(m/T)*(sum[d]-sum[T-]);//1ll是把int变成long long然后再赋值给long long,是怕int不够存的
//知道看到这个位置,我才知道sum的含义。sum是指Σ(p|T)μ(T/p) //这里是啥啊????!
//这里大概是整除分块,有许多[n/i]的值是一样的,而且它们呈一个块状分布
}
print(ans);
}
return ;
}

P2257 YY的GCD--洛谷luogu的更多相关文章

  1. 洛谷 P2257 YY的GCD

    洛谷 P2257 YY的GCD \(solution:\) 这道题完全跟[POI2007]ZAP-Queries (莫比乌斯反演+整除分块) 用的一个套路. 我们可以列出答案就是要我们求: \(ans ...

  2. [Luogu P2257] YY的GCD (莫比乌斯函数)

    题面 传送门:洛咕 Solution 推到自闭,我好菜啊 显然,这题让我们求: \(\large \sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)\in prime]\) 根 ...

  3. P2257 YY的GCD

    P2257 YY的GCD 题目描述 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对 k ...

  4. 题解 P2257 YY的GCD

    P2257 YY的GCD 解题思路 果然数论的题是真心不好搞. 第一个莫比乌斯反演的题,好好推一下式子吧..(借鉴了blog) 我们要求的答案就是\(Ans=\sum\limits_{i=1}^{n} ...

  5. P1654 OSU!-洛谷luogu

    传送门 题目背景 原 <产品排序> 参见P2577 题目描述 osu 是一款群众喜闻乐见的休闲软件. 我们可以把osu的规则简化与改编成以下的样子: 一共有n次操作,每次操作只有成功与失败 ...

  6. 洛谷 - P2257 - YY的GCD - 莫比乌斯反演 - 整除分块

    https://www.luogu.org/problemnew/show/P2257 求 \(n,m\) 中 \(gcd(i,j)==p\) 的数对的个数 求 $\sum\limits_p \sum ...

  7. 洛谷 P2257 YY的GCD 题解

    原题链接 庆祝: 数论紫题 \(T4\) 达成! 莫比乌斯 \(T1\) 达成! yy 真是个 神犇 前记 之前我觉得: 推式子,直接欧拉筛,筛出个 \(\phi\),然后乱推 \(\gcd\) 就行 ...

  8. 洛谷 P2257 - YY的GCD(莫比乌斯反演+整除分块)

    题面传送门 题意: 求满足 \(1 \leq x \leq n\),\(1 \leq y \leq m\),\(\gcd(x,y)\) 为质数的数对 \((x,y)\) 的个数. \(T\) 组询问. ...

  9. 洛谷P2257 YY的GCD 莫比乌斯反演

    原题链接 差不多算自己推出来的第一道题QwQ 题目大意 \(T\)组询问,每次问你\(1\leqslant x\leqslant N\),\(1\leqslant y\leqslant M\)中有多少 ...

  10. 洛谷P2257 YY的GCD

    今日份是数论 大概是..从小学奥数到渐渐毒瘤 那就简单列一下目录[大雾 同余 质数密度 唯一分解定理 互质 完全剩余系 简化剩余系 欧拉函数 逆元 斐蜀定理 阶(及其性质) 欧拉定理 费马小定理 原根 ...

随机推荐

  1. Vue基础01vue的基本示例,vue的双向数据绑定,vue中常见的几种用法,vue相关常见指令

    自学vue框架,每天记录重要的知识点,与大家分享!有不足之处,希望大家指正. 本篇将讲述:vue的基本示例,vue的双向数据绑定,vue中常见的几种用法,vue相关常见指令 前期学习基础,使用vue. ...

  2. 学习之路-前端-笔记-一、HTML笔记

    各种技巧 1.在Webstrom中 同时按ctrl+alt+insert创建新内容 2.输入标签按tab自动补全 按end 或 HOME实现光标移动到当前行的最后或最前 3.按住alt键不放同时按鼠标 ...

  3. JavaScript面向对象编程指南(六) 继承

    第6章 继承 6.1 原型链 6.1.1原型链示例 原型链法:Child.prototype=new Parent(); <script> function Shape(){ this.n ...

  4. mysql随笔系列-1

    MySQL数据库管理 本人实验所用的MySQL数据库版本:5.5.56-MariaDB MariaDB Server  操作系统:centos7.5 1.创建数据库 MariaDB [(none)]& ...

  5. OpenVDB for Mitsuba

    https://github.com/zhoub/mitsuba-vdb

  6. JPTabBar 详细介绍

    一个强大的TabBar,实现市面上APP基本上所拥有的功能,代码简单构造容易!只需不足5行代码就把基本的界面搭建出来了 附上效果图: 主要功能特色: 多种Tab切换的动画效果 实现底部导航中间按钮凸出 ...

  7. Android包管理机制(二)PackageInstaller安装APK

    前言 在本系列上一篇文章Android包管理机制(一)PackageInstaller的初始化中我们学习了PackageInstaller是如何初始化的,这一篇文章我们接着学习PackageInsta ...

  8. Linux 之父自传《just for fun》读书笔记

    一次偶然的机会,看到了阮一峰老师关于这本书的介绍,当时我就觉得这本书相当有趣. 在没有读这本书之前,我觉得 linus 作为发明 Linux 系统的人,应该是一个比较严肃的人,就像我的老师一样.但事实 ...

  9. Spring Data Redis 让 NoSQL 快如闪电(2)

    [编者按]本文作者为 Xinyu Liu,文章的第一部分重点概述了 Redis 方方面面的特性.在第二部分,将介绍详细的用例.文章系国内 ITOM 管理平台 OneAPM 编译呈现. 把 Redis ...

  10. mysql初始化提示安装perl

    all_db --user=mysql --datadir=/data/mysql", "delta": "0:00:00.222500", &quo ...