前言

数学符号约定:

  1. \(a\)、\(b\)、\(m\)、\(n\)、\(x\)、\(y\):任意一个正整数。

  2. \(p\):任意一个质数。

  3. \(d\):一个数的任意一个因子。

  4. \(\varphi(n)\):欧拉函数。

  5. \(d \mid n\):\(d\) 能整除 \(n\) 或 \(d\) 是 \(n\) 的因子。

  6. \(m \perp n\):\(m\) 和 \(n\) 互质。

若无特殊说明,则本篇文章的数学符号将会严格按照上述约定编写。

题目描述:

给定一个正整数 \(n \, (n \le 10^9)\),求 \(\varphi (n)\),有多组数据。

题目分析:

这是一个非常非常裸的欧拉函数板子,鉴于可能有同学不知道欧拉函数,本篇文章就简单介绍一下欧拉函数。

欧拉函数:


  1. 定义:对于正整数 \(n\),欧拉函数是所有小于等于 \(n\) 的数中与 \(n\) 互质的数的个数。

  2. 计算式:\(\varphi(n) = n \times \prod_{p \mid n}\frac{p-1}{p}\)

  3. 推论:\(\forall p \in Primes \,,\, \varphi(p)=p-1\)

由欧拉函数的计算式,我们可以看出,对于求出 \(\varphi(n)\) 的值,我们可以先用线性筛预处理出 \(\sqrt n\) 个质数,然后用筛出来的质数来求出 \(\varphi(n)\) 的值。

然而,这里有一个小 trick,就是我们不需要所有的 \(n\) 用上述方法求 \(\varphi(n)\) 的值,因为根据欧拉函数的推论可知,对于所有的质数,其欧拉函数的值等于小于自己的所有正整数的个数。

所以我们可以先行判断 \(n\) 是否为质数,如果为质数,则直接输出 \(n-1\),否则计算其 \(\varphi(n)\) 的值。

对于质数的判定,我们这里可以使用时间复杂度为 \(\Theta(\lg n)\) 的 Miller-Rabin 素性测试。

Miller-Rabin 素性测试:


首先,我们先了解一下费马小定理:

\[\forall p \in Primes \,,\,a^{p-1} \equiv 1\pmod p
\]

对此,我们可以有一个 idea,对于一个数 \(n\),我们先随机一个 \(a\),判断一下是否有 \(a^{n-1} \equiv 1 \pmod n\),如果该式不成立,则我们可以判定 \(n\) 一定为合数。

但是对此,我们却不能确定 \(n\) 一定是质数,因为存在像 \(561\) 这样的 CarMichael 数(也叫费马伪素数)无法判断出来。

对此,我们引入二次探测定理:若 \(p\) 为奇素数,且 \(0 < x < p\),则 \(x^2 \equiv 1 \pmod p\) 的解为 \(x\equiv 1 \pmod p\) 或 \(x \equiv p-1 \pmod p\)。

Miller-Rabin 素性测试就是将费马小定理与二次探测定理结合使用来判断一个数是否有极大概率为质数,他的具体做法如下:

  • 将 \(n-1\) 表示为 \(u \times 2^t\),先测试 \(a^{u \times 2^t} \equiv 1 \pmod n\) 是否成立,若不成立,则证明 \(n\) 为合数,若成立,则进行下一步。

  • 若 \(a^u \equiv 1 \pmod n\) 成立,或者存在某个整数 \(0 \le y \le t-1\),使得 \(a^{u \times 2^y} \equiv 1 \pmod n\) 成立,则称 \(n\) 通过 Miller 测试

Miller-Rabin 的算出错误结果的概率小于等于 \(\dfrac 14\),若反复测试 \(k\) 次,则算出错误结果的概率小于等于 \((\dfrac 14)^k\),这里建议测试次数为 \(20\) 次左右。

代码实现:

#include <bits/stdc++.h>
using namespace std; #define MAX_SIZE (int)6e5
#define int long long long long primes[MAX_SIZE];
bool nf[MAX_SIZE]; long long fastpow(long long base, long long index, long long mod) { //快速幂
long long ans = 1; while (index) {
if (index & 1)
ans = ans % mod * (base % mod) % mod; base = base % mod * (base % mod) % mod;
index >>= 1;
} return ans;
} void primeshai(long long num) { //线性筛
int fin = sqrt(num); for (int i = 2; i <= fin; i++) {
if (!nf[i])
primes[++primes[0]] = i; for (int j = 1; j <= primes[0] && primes[j]*i <= fin; j++) {
nf[primes[j]*i] = 1; if (i % primes[j] == 0)
break;
}
}
} long long phi(long long num) { //计算欧拉函数
long long fin = sqrt(num);
long long ans = num; for (long long i = 1; i <= primes[0] && primes[i] <= fin; i++) {
if (num % primes[i] == 0) {
ans /= primes[i];
ans *= (primes[i] - 1);
} while (num % primes[i] == 0)
num /= primes[i];
} if (num > 1) {
ans /= num;
ans *= (num - 1);
} return ans;
} bool Miller_Rabin(long long n, int test_time = 20) { // Miller_Rabin 素性测试
if (n < 3 || (n & 1) == 0)
return n == 2; long long a = n - 1;
long long b = 0; while (!(a & 2))
a >>= 1, ++b; for (int i = 1, j; i <= test_time; ++i) {
long long x = rand() % (n - 1) + 1;
long long v = fastpow(x, a, n); if (v == 1)
continue; for (j = 0; j < b; ++j) {
if (v == n - 1)
break; v = (long long)v * v % n;
} if (j >= b)
return 0;
} return 1;
} signed main() {
primeshai(1e9 + 10); //预处理出根号1e9+10内质数
srand(time(0));
long long n; while (cin >> n) {
if (n == 0)
break; if (n == 1) //特判一下 n 为 1 的情况
cout << 0 << endl;
else if (Miller_Rabin(n)) //如果 n 为质数,则输出 n-1
cout << n - 1 << endl;
else
cout << phi(n) << endl;
} return 0;
}

Update 记录:

  1. \(2022.8.11\):修改了一些小的细节错误。

题解 UVA10299的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

  10. JSOI2016R3 瞎BB题解

    题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...

随机推荐

  1. F-Beta-Score

    F1-Score相关概念 F1分数(F1 Score),是统计学中用来衡量二分类(或多任务二分类)模型精确度的一种指标.它同时兼顾了分类模型的准确率和召回率. F1分数可以看作是模型准确率和召回率的一 ...

  2. selenium报错:This version of ChromeDriver only supports Chrome version 109 Current browser version is 112.0.5615.49...解决办法

    前言:跟GPT交互,让其写一段代码,执行失败.经过排查验证,GPT写的代码没有问题,是本地环境问题. 执行报错: selenium.common.exceptions.SessionNotCreate ...

  3. Flutter系列文章-Flutter UI进阶

    在本篇文章中,我们将深入学习 Flutter UI 的进阶技巧,涵盖了布局原理.动画实现.自定义绘图和效果.以及 Material 和 Cupertino 组件库的使用.通过实例演示,你将更加了解如何 ...

  4. Sourcetrail 代码分析工具的使用

    Sourcetrail 概述 Sourcetrail 是一个代码分析工具,它旨在帮助开发人员理解和导航复杂的代码库.它可以创建代码库的可视化图形,显示代码中的类.函数.变量.依赖关系等信息,从而帮助开 ...

  5. 【JMeter】使用BeanShell写入内容到文件

    使用BeanShell写入内容到文件 目录 使用BeanShell写入内容到文件 一.前言 二.提取 三.写入 一.前言 ​ 在我们日常工作中,可能会遇到需要将请求返回的数据写入到文件中.在我们使用J ...

  6. 文心一言 VS 讯飞星火 VS chatgpt (81)-- 算法导论7.4 6题

    六.如果用go语言,考虑对 PARTITION 过程做这样的修改:从数组 A 中随机选出三个元素,并用这三个元素的中位数(即这三个元素按大小排在中间的值)对数组进行划分.求以a 的函数形式表示的.最坏 ...

  7. 关于ChatGPT的一些闲扯淡(1)

    这篇写的有点迟了,前者子ChatGPT正火的时候,懒病发作一直拖延.今天对ChatGPT做一个简单的讨论,也是把学习的心得和大家分享一下. 首先什么是GPT,英文全称是Generative Pretr ...

  8. 《SQL与数据库基础》21. 分库分表(一)

    目录 分库分表(一) 拆分策略 垂直拆分 垂直分库 垂直分表 水平拆分 水平分库 水平分表 技术实现 MyCat概述 概念介绍 环境准备 目录介绍 MyCat入门 配置 分片配置(schema.xml ...

  9. 2.7 PE结构:重定位表详细解析

    重定位表(Relocation Table)是Windows PE可执行文件中的一部分,主要记录了与地址相关的信息,它在程序加载和运行时被用来修改程序代码中的地址的值,因为程序在不同的内存地址中加载时 ...

  10. Spring Cloud LoadBalancer原理讲解及自定义负载均衡器

    Spring Cloud LoadBalancer原理 LoadBalancerClient作为负载均衡客户端,用于进行负载均衡逻辑,从服务列表中选择出一个服务地址进行调用,其内部方法为下图显示: ( ...