「BZOJ3884」 上帝与集合的正确用法

Description

(large{2^{2^{2^{2^{cdots}}}} mod p}) 的值。

(T) 组测试数据。

Hint

(1le Tle 10^3,1le ple 10^7)

Solution

首先,我们有 扩展欧拉定理

(large{a^b equiv egin{cases} a^{bmod varphi(p) + varphi(p)} & b > varphi(p) \ a^b end{cases} pmod p})

那么,对于 (b > varphi(p)) ,原式就等于:

(large{2^{[(2^{2^{2^{cdots}}}) mod varphi(p) +varphi(p)]}})

然后显然这就是一个递归式子,直接计算即可。当 (p=1) 时,停止递归。

超时?不存在的。

由于 (p > varphi(p)) 所以这个 (p) 会一直减小,直到为 (1)

并且减小的非常快。

于是就通过了此题。

Code

/*
 * Author : _Wallace_
 * Source : https://www.cnblogs.com/-Wallace-/
 * Problem : BZOJ3884 上帝与集合的正确用法
 */
#include<cstdio>
#include<algorithm>
using namespace std;

const int N=1e7+5;
int phi[N];

void init_phi(int n) {
	phi[1]=1;
	for(register int i=2;i<=n;i++) if(!phi[i])
		for(register int j=i;j<=n;j+=i) {
			if(!phi[j]) phi[j]=j;
			phi[j]=phi[j]/i*(i-1);
		}
}

long long fp(long long a,long long b,long long c) {
	if(!b) return 1ll%c;
	long long t=fp(a,b>>1,c);
	if(b&1) return t*t%c*a%c;
	else return t*t%c;
}

long long solve(int p) {
	return (p==1)?0ll:fp(2,solve(phi[p])+phi[p],p);
}

signed main() {
	init_phi(1e7);
	int T; scanf("%d",&T);
	while(T--) {
		int p; scanf("%d",&p);
		printf("%lld
",solve(p));
	}
}
原文地址:https://www.cnblogs.com/-Wallace-/p/12602362.html