P4139 上帝与集合的正确用法

思路:扩展欧拉定理

提交:\(1\)

题解:

首先简介扩展欧拉定理:
\(b>=\varphi(p)\)时,\(a^b\equiv a^{b\%\varphi(p)+\varphi(p)} \mod p\)
这样我们可以递归去算这个式子,直到\(p==1\),因为\(2^{2^{2^\cdots}}\)永远是无穷大的。

代码:

#include<cstdio>
#include<iostream>
#define ll long long
#define R register ll
using namespace std;
namespace Luitaryi {
template<class I> inline I g(I& x) { x=0;
	register I f=1; register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
} const int N=1e7+10;
int T,x,cnt,p[N>>1],phi[N];
bool v[N];
inline void PRE() { phi[1]=1;
	for(register int i=2;i<=N-10;++i) {
		if(!v[i]) p[++cnt]=i,phi[i]=i-1;
		for(register int j=1;j<=cnt&&i*p[j]<=N-10;++j) {
			v[i*p[j]]=true;
			if(i%p[j]==0) {
				phi[i*p[j]]=phi[i]*p[j]; break;
			} phi[i*p[j]]=phi[i]*(p[j]-1);
		}
	} 
} 
inline int qpow(int p,int M) { R a=2,ret=1;
	for(;p;p>>=1,(a*=a)%=M) if(p&1) (ret*=a)%=M; return ret;
}
inline int calc(int x) {
	if(x==1) return 0;
	return qpow(phi[x]+calc(phi[x]),x);
}
inline void main() {
	PRE(); g(T); while(T--) {
		g(x); printf("%d\n",calc(x));
	}
}
} signed main() {Luitaryi::main(); return 0;}

2019.08.23
77

posted @ 2019-08-23 17:17  LuitaryiJack  阅读(151)  评论(0编辑  收藏  举报