ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P4139 上帝与集合的正确用法

2021-11-17 09:06:31  阅读:199  来源: 互联网

标签:prime 上帝 phi int varphi 用法 P4139 vis mod


原题传送门

题意: T T T组数据,对于每个模数 p p p,求 2 2 2 . . . m o d 2^{2^{2^{...}}} mod 222...mod p p p, T ≤ 1 0 3 T\le 10^3 T≤103, p ≤ 1 0 7 p\le 10^7 p≤107

思路:扩展欧拉定理
显然 2 2 . . . {2^{2^{...}}} 22...这个无限数,是大于 φ ( p ) \varphi(p) φ(p)的,那么由扩展欧拉定理可得:
对于 b ≥ φ ( p ) b\ge \varphi(p) b≥φ(p),
有 a b ≡ a b   m o d   φ ( p ) + φ ( p )   m o d   p a^b\equiv a^{b\ mod\ \varphi(p)+\varphi(p)}\ mod\ p ab≡ab mod φ(p)+φ(p) mod p
很显然这个是递归式子,模数 φ ( p ) \varphi(p) φ(p)很快会降为 1 1 1,此时式子为 0 0 0
对于 φ ( p ) \varphi(p) φ(p),我们可以用线性筛预处理得到
时间复杂度: O ( p + T l o g   p ) O(p+Tlog\ p) O(p+Tlog p)

接下来我们谈一下,如何用线性筛预处理欧拉函数 φ ( x ) \varphi(x) φ(x)
对于 φ ( x ) \varphi(x) φ(x)我们利用如下性质:

  • φ ( x ) = x − 1 \varphi(x)=x-1 φ(x)=x−1, x ∈ p r i m e x\in prime x∈prime
  • φ ( x k ) = x k − x k − 1 \varphi(x^k)=x^k-x^{k-1} φ(xk)=xk−xk−1, x ∈ p r i m e x\in prime x∈prime
  • g c d ( m , n ) = 1 gcd(m,n)=1 gcd(m,n)=1, φ ( m n ) = φ ( m ) φ ( n ) \varphi(mn)=\varphi(m) \varphi(n) φ(mn)=φ(m)φ(n)

由此,我们得到欧拉函数是个积性函数,而线性筛可以预处理积性函数
Code

bool vis[N];
int cnt,prime[N/10],phi[N],p,t;
void get_phi(int n){
	phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			prime[++cnt]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0){
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			else phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
}

套用这个模板,本题就很容易了
Code

#include <bits/stdc++.h>
using namespace std;
const int N=1e7+10;
typedef long long ll;
bool vis[N];
int cnt,prime[N/10],phi[N],p,t;
void get_phi(int n){
	phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			prime[++cnt]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0){
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			else phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
}
int power(int a,int b,int p){
	int res=1;
	for(;b;b>>=1){
		if(b&1) res=1LL*res*a%p;
		a=1LL*a*a%p;
	}
	return res;
}
int solve(int x){
	if(x==1) return 0;
	return power(2,solve(phi[x])+phi[x],x);
}
int main(){
	get_phi(N);
	cin>>t;
	while(t--){
		cin>>p;
		cout<<solve(p)<<endl;
	}
	return 0;
}

标签:prime,上帝,phi,int,varphi,用法,P4139,vis,mod
来源: https://blog.csdn.net/qq_53287227/article/details/121369900

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有