ACM学习历程—HYSBZ 2818 Gcd(欧拉函数 || 莫比乌斯反演)
Description
给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.
Input
一个整数N
Output
如题
Sample Input
4
Sample Output
4
Hint
对于样例(2,2),(2,4),(3,3),(4,2)
1<=N<=10^7
这个题目可以用欧拉函数或者莫比乌斯反演。
第一种欧拉函数:
因为gcd(x, y) = p,所以gcd(x/p, y/p) = 1。
不妨设y较大,那么就是求所有比y/p小的数k,phi(k)的和。phi(k)是欧拉函数,表示小于等于k,与k互质的数的个数。
然后每种乘2就得到了组数,但是需要减1,因为(1, 1)这组被计算了两次。
预处理所有phi(k)的前缀和就OK了,就能加速运算。
然后枚举质数p就OK了。
这个OJ我揣测是单组测试的,像下面预处理打表会T,需要对每个n进行一次打表。
代码:(欧拉函数)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <algorithm>
#define LL long long using namespace std; const int maxN = 1e7+;
int n;
bool isprim[maxN];
int phi[maxN], prim[maxN], top;
LL s[maxN]; //埃氏筛法求素数
void isPrim()
{
top = ;
memset(isprim, true, sizeof(isprim));
isprim[] = isprim[] = false;//初始化
for (LL i = ; i < maxN; ++i)//筛法
{
if (isprim[i])
{
for (LL j = i*i; j < maxN; j += i)//上界太大可能会爆int
{
isprim[j] = false;
}
prim[top++] = i;
}
}
} //***筛法求欧拉函数
void phi_table()
{
memset(phi, , sizeof(phi));
phi[] = ;
s[] = ;
s[] = ;
for (int i = ; i < maxN; i++)
{
if (!phi[i])
for (LL j = i; j < maxN; j += i)//i如果太大可能会爆int
{
if (!phi[j])
phi[j] = j;
phi[j] = phi[j]/i*(i-);
}
s[i] = s[i-]+phi[i];
}
} void work()
{
LL ans = ;
for (int i = ; i < top && prim[i] <= n; ++i)
{
ans += *s[n/prim[i]];
ans--;
}
printf("%lld\n", ans);
} int main()
{
//freopen("test.in", "r", stdin);
isPrim();
phi_table();
while (scanf("%d", &n) != EOF)
{
work();
}
return ;
}
第二种莫比乌斯反演:
设F(d)表示d | gcd(x, y) (1 <= x <= N, 1 <= y <= M)
f(d)表示d = gcd(x, y) (1 <= x <= N, 1 <= y <= M)
那么自然F(d) = sum(f(n)) (d | n)
且F(d) = (N/d)*(M/d)
根据莫比乌斯反演:
F(d) = sum(f(n)) (d|n) => f(d) = sum(u(n/d)*F(n)) (d|n)
所以f(d) = f(d) = sum(u(n/d)*F(n)) (d|n)
然后d取遍质数
则ans = sum(f(p)) = sum( sum(u(n/p)*F(n)) (p|n) )
外层sum上界为min(M, N), 内层sum也为min(M, N)
这样复杂度是min(M^2, N^2)的,时间上过不去。
此外就是这两个sum的位置是可以替换的,
因为整个式子的结果就是所有p|n的情况都要加上,
原式是对于一个p把所有n的情况加起来,最后求和。
同样可以,对于每一个n把所有p的情况加起来,最后求和。
那么式子可以改写为:ans = sum( F(n)*sum(u(n/p)) ) (p|n)
这样,如果能在时限内预处理出每个n对应的sum(u(n/p)),那么就能在min(M, N)时间复杂度内求解。
这里可以先把所有sum初始化为0,然后类似于筛法的做法,对于一个p,把所有p的倍数n的sum,加上u(n/p)。
这样预处理的复杂度要nlogn左右。不过常数有点大,本地需要1S多才能跑出来。(网上有一种O(n)的做法)
同样的,下面的打表也会T,需要对每个n进行一次打表。
代码:(莫比乌斯)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#define LL long long using namespace std; const int maxN = 1e7+;
int u[maxN], cnt;
LL prime[maxN], sum[maxN];
bool vis[maxN]; void mobius()
{
memset(vis, false,sizeof(vis));
u[] = ;
cnt = ;
for(LL i = ; i < maxN; i++)
{
if(!vis[i])
{
prime[cnt++] = i;
u[i] = -;
}
for(int j = ; j < cnt && i*prime[j] < maxN; j++)
{
vis[i*prime[j]] = true;
if(i%prime[j])
u[i*prime[j]] = -u[i];
else
{
u[i*prime[j]] = ;
break;
}
}
}
} int n;
LL ans; void init()
{
mobius();
ans = ;
memset(sum, , sizeof(sum));
for (int i = ; i < cnt; ++i)
{
for (LL j = prime[i]; j < maxN; j += prime[i])
sum[j] += u[j/prime[i]];
}
} void work()
{
for (LL i = ; i <= n; ++i)
ans += (n/i)*(n/i)*sum[i];
printf("%lld\n", ans);
} int main()
{
//freopen("test.in", "r", stdin);
init();
while (scanf("%d", &n) != EOF)
work();
return ;
}
ACM学习历程—HYSBZ 2818 Gcd(欧拉函数 || 莫比乌斯反演)的更多相关文章
- 洛谷P2568 GCD (欧拉函数/莫比乌斯反演)
P2568 GCD 题目描述 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. 输入输出格式 输入格式: 一个整数N 输出格式: 答案 输入输出样例 输入 ...
- BZOJ 2818: Gcd [欧拉函数 质数 线性筛]【学习笔记】
2818: Gcd Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4436 Solved: 1957[Submit][Status][Discuss ...
- BZOJ 2818 GCD 【欧拉函数 || 莫比乌斯反演】
传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=2818 2818: Gcd Time Limit: 10 Sec Memory Limit ...
- UVA11426 GCD - Extreme (II) (欧拉函数/莫比乌斯反演)
UVA11426 GCD - Extreme (II) 题目描述 PDF 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 10 100 200000 0 输出样例#1: 67 13 ...
- 51nod 1237 最大公约数之和 V3【欧拉函数||莫比乌斯反演+杜教筛】
用mu写lcm那道卡常卡成狗(然而最后也没卡过去,于是写一下gcd冷静一下 首先推一下式子 \[ \sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j) \] \[ \sum_{i= ...
- 中国剩余定理 & 欧拉函数 & 莫比乌斯反演 & 狄利克雷卷积 & 杜教筛
ssplaysecond的博客(请使用VPN访问): 中国剩余定理: https://ssplaysecond.blogspot.jp/2017/04/blog-post_6.html 欧拉函数: h ...
- BZOJ 2818 Gcd(欧拉函数+质数筛选)
2818: Gcd Time Limit: 10 Sec Memory Limit: 256 MB Submit: 9108 Solved: 4066 [Submit][Status][Discu ...
- bzoj 2818 Gcd(欧拉函数 | 莫比乌斯反演)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2818 [题意] 问(x,y)为质数的有序点对的数目. [思路一] 定义f[i]表示i之 ...
- hdu6390 /// 欧拉函数+莫比乌斯反演 筛inv[] phi[] mu[]
题目大意: 给定m n p 求下式 题解:https://blog.csdn.net/codeswarrior/article/details/81700226 莫比乌斯讲解:https://ww ...
随机推荐
- 使用UIImageView展现来自网络的图片
本文转载至 http://www.cnblogs.com/chivas/archive/2012/05/21/2512324.html UIImageView:可以通过UIImage加载图片赋给UII ...
- Windows下oracle-win-64-11g安装步骤
一. Oracle 下载 官方下地址 http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.htm ...
- 九度OJ 1336:液晶屏裁剪 (GCD)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:983 解决:228 题目描述: 苏州某液晶厂一直生产a * b大小规格的液晶屏幕,由于该厂的加工工艺限制,液晶屏的边长都为整数.最近由于市场 ...
- python 学习2:生成器,迭代器,装饰器
1.生成器 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万 个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那 ...
- mysql练习(待补充)
2.查询‘生物’课程比‘物理’课程成绩高的所有学生的学号 思路: 获取所有生物课程的人(学号,成绩)-临时表 获取所有物理课程的人(学号,成绩)-临时表 根据学号连接两个临时表: 学号 生物成绩 物理 ...
- 牛客小白月赛1 D 多项式乘法 【循环】
题目链接 https://www.nowcoder.com/acm/contest/85/D 思路 因为数据范围较小 ,所以 可以直接 一个一个乘 AC代码 #include <cstdio&g ...
- 简介windows的环境变量
环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,比如临时文件夹位置和系统文件夹位置等.这点有点类似于DOS时期的默认路径,当你运行某些程序时除了在当前文件夹中寻找外,还会到设置的默认路 ...
- c++ 之重要性
c++的功能比c语言大的多,c语言偏最底层,且程序短小,而对于一个大的系统,用c++,因为它具备了c语言的优点. 很多学嵌入式的觉得学了c语言之后,就不用学c++了,会认为c++很简单,然而,c++并 ...
- ubuntu下android studio生成的unaligned apk的zipalign处理
在ubuntu系统中使用android studio生成的apk文件始终都是unaligned apk, 在bulid.gradle中设置如下设置后,还是同样生成的是unaligned apk. mi ...
- python核心编程3-13
3.13: 添加新功能. 将你上一个问题改造好的readNwriteTextFiles.py 增加一个新功能: 允许用户编辑一个已经存在的文本文件. 你可以使用任何方式,无论是一次编辑一行,还是一次编 ...