莫比乌斯反演进阶-洛谷P2257/HDU5663
学了莫比乌斯反演之后对初阶问题没有任何问题了,除法分块也码到飞起,但是稍微变形我就跪了。用瞪眼观察法观察别人题解观察到主要内容除了柿子变形之外,主要就是对于miu函数的操作求前缀和。进而了解miu函数,miu函数是在这个数是否有平方因子的个数,每次推的套路是先用欧拉筛筛出来所有需要的函数,然后用每次需要用到的函数进行累计迭代加到前缀和,二次过筛,然后堆起来前缀和,用除法分块就行了,这个方法屡试不爽。
两道题,一道是洛谷P2257 YY的GCD
这道题求的是1-n和1-m区间内gcd为质数的个数,对此我们有暴力O(nmtlogn)算法,用莫比乌斯反演之后,我们枚举质数,每次来一遍分块,可以降到O(t * sqrtn + n),显然对于1e7这种级别的,质数都有66w个,复杂度显而易见是不够优秀的,那么我们需要一些加速,就是用前缀和处理出来这个区间内有质数gcd的数目,然后跑分块就可行了,复杂度根号


#include <bits/stdc++.h>
using namespace std;
#define limit (10000000 + 5)//防止溢出
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define FASTIO ios::sync_with_stdio(false);cin.tie(0);
#define ff(a) printf("%d\n",a );
#define pi(a,b) pair<a,b>
#define rep(i, a, b) for(ll i = a; i <= b ; ++i)
#define per(i, a, b) for(ll i = b ; i >= a ; --i)
#define MOD 998244353
#define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next)
#define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\data.txt", "rt", stdin)
#define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\dabiao.txt", "wt", stdout)
#define debug(x) cout<<x<<endl
typedef long long ll;
typedef unsigned long long ull;
inline ll read(){
ll sign = 1, x = 0;char s = getchar();
while(s > '9' || s < '0' ){if(s == '-')sign = -1;s = getchar();}
while(s >= '0' && s <= '9'){x = (x << 3) + (x << 1) + s - '0';s = getchar();}
return x * sign;
}//快读
void write(ll x){
if(x < 0) putchar('-'),x = -x;
if(x / 10) write(x / 10);
putchar(x % 10 + '0');
}
int prime[limit],tot,num[limit],miu[limit];
ll sum[limit];
void get_prime(const int &n = 1e7){
memset(num,1,sizeof(num));
num[1] = num[0] = 0;
miu[1] = 1;
rep(i,2,n){
if(num[i])prime[++tot] = i,miu[i] = -1;
for(int j = 1; j <= tot && prime[j] * i <= n ; ++j){
num[prime[j] * i] = 0;
if(i % prime[j] == 0){
miu[i * prime[j]] = 0;
break;
}else{
miu[i * prime[j]] = -miu[i];//莫比乌斯函数
}
}
}
rep(i ,1,tot){
for(int j = prime[i] ; j <= n ; j += prime[i]){
sum[j] += miu[j / prime[i]];//几个平方因子
}
}
rep(i ,1,n){
sum[i] += sum[i-1];
} }//素数筛
ll n,m;
const ll d = 1;
ll calc(){
ll ans = 0;
for(int l = 1,r ; l <= min(n/d,m/d); l = r + 1){
//值域分块
ll t = n / d , s = m / d;
r = min(t / (t / l), s / (s / l));
ans += (sum[r] - sum[l - 1]) * (t / l) * (s / l);
} return ans;
}
int main() {
#ifdef LOCAL
FOPEN;
#endif
get_prime(10000000);
int kase = read();
while (kase--){
n = read(), m = read();
write(calc()),putchar('\n');
}
return 0;
}
AC Code
吐槽一下卡常,这卡得什么玩意儿,快读快写都上吸了氧才ac,吐了吐了
然后是HDU 5663
这题一看就特别熟悉,直接处理出是平方数的μ前缀和,然后跑一边莫比乌斯反演就行


#include <bits/stdc++.h>
using namespace std;
#define limit (10000000 + 5)//防止溢出
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define FASTIO ios::sync_with_stdio(false);cin.tie(0);
#define ff(a) printf("%d\n",a );
#define pi(a,b) pair<a,b>
#define rep(i, a, b) for(ll i = a; i <= b ; ++i)
#define per(i, a, b) for(ll i = b ; i >= a ; --i)
#define MOD 998244353
#define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next)
#define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\data.txt", "rt", stdin)
#define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\dabiao.txt", "wt", stdout)
#define debug(x) cout<<x<<endl
typedef long long ll;
typedef unsigned long long ull;
inline ll read(){
ll sign = 1, x = 0;char s = getchar();
while(s > '9' || s < '0' ){if(s == '-')sign = -1;s = getchar();}
while(s >= '0' && s <= '9'){x = (x << 3) + (x << 1) + s - '0';s = getchar();}
return x * sign;
}//快读
void write(ll x){
if(x < 0) putchar('-'),x = -x;
if(x / 10) write(x / 10);
putchar(x % 10 + '0');
}
int prime[limit],tot,num[limit],miu[limit];
ll sum[limit];
void get_prime(const int &n = 1e7){
memset(num,1,sizeof(num));
num[1] = num[0] = 0;
miu[1] = 1;
rep(i,2,n){
if(num[i])prime[++tot] = i,miu[i] = -1;
for(int j = 1; j <= tot && prime[j] * i <= n ; ++j){
num[prime[j] * i] = 0;
if(i % prime[j] == 0){
miu[i * prime[j]] = 0;
break;
}else{
miu[i * prime[j]] = -miu[i];//莫比乌斯函数
}
}
}
for(int i = 1 ; i * i <= n ; ++i){
for(int j = i * i ; j <= n ; j += i * i){
sum[j] += miu[j / i / i];//记录所有的平方
}
}
rep(i,2,n){
sum[i] += sum[i-1];
}
}//素数筛
ll n,m;
const ll d = 1;
ll calc(){
ll ans = 0;
for(int l = 1,r ; l <= min(n/d,m/d); l = r + 1){
//值域分块
ll t = n / d , s = m / d;
r = min(t / (t / l), s / (s / l));
ans += (sum[r] - sum[l - 1]) * (t / l) * (s / l);
} return ans;
}
int main() {
#ifdef LOCAL
FOPEN;
#endif
get_prime(1e7 + 1);
int kase = read();
rep(ka,1,kase){
n = read(), m = read();
printf("%lld\n",n * m - calc());
}
return 0;
}
AC Code
嘿哈
莫比乌斯反演进阶-洛谷P2257/HDU5663的更多相关文章
- 洛谷 P2257 YY的GCD
洛谷 P2257 YY的GCD \(solution:\) 这道题完全跟[POI2007]ZAP-Queries (莫比乌斯反演+整除分块) 用的一个套路. 我们可以列出答案就是要我们求: \(ans ...
- 洛谷 P2257 - YY的GCD(莫比乌斯反演+整除分块)
题面传送门 题意: 求满足 \(1 \leq x \leq n\),\(1 \leq y \leq m\),\(\gcd(x,y)\) 为质数的数对 \((x,y)\) 的个数. \(T\) 组询问. ...
- 洛谷P2257 YY的GCD 莫比乌斯反演
原题链接 差不多算自己推出来的第一道题QwQ 题目大意 \(T\)组询问,每次问你\(1\leqslant x\leqslant N\),\(1\leqslant y\leqslant M\)中有多少 ...
- 洛谷P2257 YY的GCD(莫比乌斯反演)
传送门 原来……莫比乌斯反演是这么用的啊……(虽然仍然不是很明白) 首先,题目所求如下$$\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=prim]$$ 我们设$f(d)$表示$g ...
- 洛谷 P2398 GCD SUM || uva11417,uva11426,uva11424,洛谷P1390,洛谷P2257,洛谷P2568
https://www.luogu.org/problemnew/show/P2398 $原式=\sum_{k=1}^n(k\sum_{i=1}^n\sum_{j=1}^n[(i,j)=k])$ 方法 ...
- 洛谷 P2257 【YY的GCD】
这道题还是和上一道[ZAP]有那么一点点的相似哈 题目大意 给定N, M,求1<=x<=N, 1<=y<=M且\(gcd(x, y)\)为质数的(x, y)有多少对 如果对莫比 ...
- 洛谷P2257 YY的GCD
今日份是数论 大概是..从小学奥数到渐渐毒瘤 那就简单列一下目录[大雾 同余 质数密度 唯一分解定理 互质 完全剩余系 简化剩余系 欧拉函数 逆元 斐蜀定理 阶(及其性质) 欧拉定理 费马小定理 原根 ...
- 洛谷 P2257 YY的GCD 题解
原题链接 庆祝: 数论紫题 \(T4\) 达成! 莫比乌斯 \(T1\) 达成! yy 真是个 神犇 前记 之前我觉得: 推式子,直接欧拉筛,筛出个 \(\phi\),然后乱推 \(\gcd\) 就行 ...
- 洛谷 - P2257 - YY的GCD - 莫比乌斯反演 - 整除分块
https://www.luogu.org/problemnew/show/P2257 求 \(n,m\) 中 \(gcd(i,j)==p\) 的数对的个数 求 $\sum\limits_p \sum ...
随机推荐
- Spring AOP实现注解式的Mybatis多数据源切换
一.为什么要使用多数据源切换? 多数据源切换是为了满足什么业务场景?正常情况下,一个微服务或者说一个WEB项目,在使用Mybatis作为数据库链接和操作框架的情况下通常只需要构建一个系统库,在该系统库 ...
- Python中的小括号()、中括号[]、花括号{}区别
Python中最常见括号的区别: 在Python语言中最常见的括号有三种,分别是:小括号().中括号[].花括号{}:其作用也不相同,分别用来代表不同的Python基本内置数据类型. Python中的 ...
- 9、Django之模型层第四篇:进阶操作
一 QuerySet对象 1.1可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. Entry.objects.all()[:5] # ...
- Python对MySQL进行增删查改
python连接MySQL数据库:pymysql # 测试操作 import pymysql # 打开数据库 db = pymysql.connect("localhost", & ...
- Android序列化问题与思考
今天再来谈谈Android中的对象序列化,你了解多少呢? 序列化指的是什么?有什么用 序列化指的是讲对象变成有序的字节流,变成字节流之后才能进行传输存储等一系列操作. 反序列化就是序列化的相反操作,也 ...
- Go语言内存分配(详述 转)
一.内存管理简介 1.1 虚拟内存 虚拟内存是当代操作系统必备的一项重要功能,对于进程而言虚拟内存屏蔽了底层了RAM和磁盘,并向进程提供了远超物理内存大小的内存空间.我们看一下虚拟内存的分层设计. 上 ...
- 美团面试官问我: ZGC 的 Z 是什么意思
本文的阅读有一定的门槛,请先了解 GC 的基本只知识. 现代垃圾收集器的演进大部分都是往减少停顿方向发展. 像 CMS 就是分离出一些阶段使得应用线程可以和垃圾回收线程并发,当然还有利用回收线程的并行 ...
- RestPack Java实现Html转PDF文件
最近公司需要将前端一个图表统计导出为pdf.前端导出显示的pdf还是可以的,但是将会导致页面不可用与卡死状态.所以由后端寻找解决方案. 以下为解决方案调研 https://www.cnblogs.co ...
- c++11-17 模板核心知识(五)—— 理解模板参数推导规则
Case 1 : ParamType是一个指针或者引用,但不是universal reference T& const T& T* Case 2 : ParamType是Univers ...
- char 和 byte 区别
byte 是字节数据类型 ,是有符号型的,占1 个字节:大小范围为-128-127 . char 是字符数据类型 ,是无符号型的,占2字节(Unicode码 ):大小范围 是0-65535 :char ...