上帝与集合的正确用法——欧拉定理
上帝与集合的正确用法
题目描述
根据一些书上的记载,上帝的一次失败的创世经历是这样的:
第一天,上帝创造了一个世界的基本元素,称做元。
第二天,上帝创造了一个新的元素,称作
第三天,上帝又创造了一个新的元素,称作
第四天,上帝创造了新的元素
如果按照这样下去,上帝创造的第四种元素将会有
然而,上帝并没有预料到元素种类数的增长是如此的迅速。他想要让世界的元素丰富起来,因此,日复一日,年复一年,他重复地创造着新的元素……
然而不久,当上帝创造出最后一种元素
至今,上帝仍记得那次失败的创世经历,现在他想问问你,他最后一次创造的元素
上帝觉得这个数字可能过于巨大而无法表示出来,因此你只需要回答这个数对p取模后的值即可。
你可以认为上帝从
一句话题意:
定义
输入格式
第一行一个整数
接下来
输出格式
样例 #1
样例输入 #1
3
2
3
6
样例输出 #1
0
1
4
提示
对于
题解
关于非质数的余数,考虑使用欧拉定理求解
原式=
显然这是一个递归式,考虑题设条件,何时为一个定值.
因为
写出代码就是:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define int long long
#define N 10000050
int phi[N], prime[1000050], tot, cnt, p, n, ans;
void init() {
phi[1] = 1;
for (int i = 2; i <= N; i++) {
if (!phi[i]) {
prime[++cnt] = i;
phi[i] = i - 1;
}
for (int j = 1; j <= cnt; j++) {
if (prime[j] * i > N)break;
int x = prime[j] * i;
phi[x] = phi[i] * (i % prime[j] ? prime[j] - 1 : prime[j]);
}
}
}
int power(int a, int b, int p) {
int ans = 1;
while (b) {
if (b & 1)ans = ans * a % p;
b >>= 1;
a = a * a % p;
}
return ans;
}
int dfs(int p) {
// printf("%lld\n",p);
if (p == 1)return 0;
return power(2, dfs(phi[p]) + phi[p], p);
}
signed main() {
init();
scanf("%lld", &p);
while (p--) {
scanf("%lld", &n);
printf("%lld\n", dfs(n) % n);
}
}
这题因为卡空间只能写埃氏筛法
再来,那么函数
int dfs(int p) {
// printf("%lld\n",p);
if (p == 1)return 0;
return power(2, dfs(phi[p]) + phi[p], p);
}
复杂度如何保证?
引理:足够大的数的欧拉函数至多是本身的一半(向上取整)
证明:
偶数的欧拉函数是本身一半,因为所有奇数都与其互质,而奇数的欧拉函数也至多是半身一本,因为所有偶数都与其互质
故函数最多递归
关于本题:
欧拉定理的推论:
设数列
求证: 当
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!