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 ...
随机推荐
- ACM暑假集训第三周小结
这一周学的图论,学了这么些 两种存图的方法:邻接矩阵( map[n][n] ) , 邻接表( headlis[n] , vector<int> G[n] )存图的方法,各有各的好,我的理解 ...
- 九度OJ 1336:液晶屏裁剪 (GCD)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:983 解决:228 题目描述: 苏州某液晶厂一直生产a * b大小规格的液晶屏幕,由于该厂的加工工艺限制,液晶屏的边长都为整数.最近由于市场 ...
- ConfigurableBeanFactory
ConfigurableBeanFactory :关系如下 在上面这样的一个关系图中可以先看下SingletonBeanRegistry的源代码: package org.springframewor ...
- 【python】-- 元组、字典
元组 元组其实跟列表差不多,也是存一组数,只不是它一旦创建,便不能再修改,所以又叫只读列表 用途:一般情况下用于自己写的程序能存下数据,但是又希望这些数据不会被改变,比如:数据库连接信息等 1.访问元 ...
- 我的Java开发学习之旅------>Base64的编码思想以及Java实现
Base64是一种用64个字符来表示任意二进制数据的方法. 用记事本打开exe.jpg.pdf这些文件时,我们都会看到一大堆乱码,因为二进制文件包含很多无法显示和打印的字符,所以,如果要让记事本这样的 ...
- Linux安装samba
说明:samba的作用是实现window环境和linux环境下的文件共享,相当于window里的网络邻居,有一定的价值,但是随着时代的发展,现在用各种ssh软件登录linux实现文件共享和传输的场景越 ...
- Docker dubbo 服务注册
vim run.sh #!/bin/baship=`ifconfig eth0 |grep "inet"|awk '{print $2}'`hn=dubbo-service-pro ...
- sap ftp 处理
[转] SAP FTP Function 本文示例如何使用SAP FTP Function将文件从应用服务器传输到另外一个FTP服务器上. DATA: BEGIN OF ig_ftp_result O ...
- Crontab使用详解
第1列分钟1-59第2列小时1-23(0表示子夜)第3列日1-31第4列月1-12第5列星期0-6(0表示星期天)第6列要运行的命令 下面是crontab的格式:分 时 日 月 星期 要运行的命令 这 ...
- jQuery中通过JSONP来跨域获取数据的三种方式
第一种方法是在ajax函数中设置dataType为'jsonp' $.ajax({ dataType: 'jsonp', url: 'http://www.a.com/user?id=123', su ...