BZOJ3844 (欧拉降幂)

题意: T T 组数据,给定 p p ,求 2 2 2 2 . . . m o d p 2^{2^{2^{2^{...\infin}}}}\bmod p
数据范围: T 1000 , p 1 0 7 T\leq 1000,p\leq 10^7

题解: 根据欧拉降幂, 2 2 2 2 . . . m o d p = 2 2 2 2 . . . m o d φ ( p ) + φ ( p ) m o d p 2^{2^{2^{2^{...\infin}}}}\bmod p= 2^{2^{2^{2^{...\infin}}}\bmod \varphi(p)+\varphi(p)}\bmod p
可以看出来递推式了,故设 f ( p ) = 2 2 2 2 . . . m o d p f(p)=2^{2^{2^{2^{...\infin}}}}\bmod p
f ( p ) = 2 f ( φ ( p ) ) + φ ( p ) m o d p f(p)=2^{f(\varphi(p))+\varphi(p)}\bmod p
这里可以线性筛筛出 φ ( n ) \varphi(n) ,或者直接 O ( n ) O(\sqrt{n}) 求每个数的 φ ( n ) \varphi(n)
证明:对于 p p

  • 如果是奇数,下次一定变成偶数,因为奇数减 1 1 为偶数,故除奇数乘偶数结果为偶数
  • 如果是偶数,至少减少 n 2 \frac{n}{2} ,因为根据欧拉函数的定义,至少要除 2 2 1 1
    故最多在 2 log p 2\log p 次后就会到 1 1 ,所以时间复杂度就是 O ( T p log p ) O(T\sqrt{p}\log p)

代码:

#include<bits/stdc++.h>
using namespace std;

int phi(int x) {
	int res = x;
	for(int i = 2; 1ll * i * i <= x; i++) {
		if(x % i == 0) {
			res = res / i * (i - 1);
			while(x % i == 0) x /= i;
		}
	}
	if(x > 1) res = res / x * (x - 1);
	return res;
} 

int qp(int a, int b, int p) {
	int ans = 1;
	while(b) {
		if(b & 1) ans = 1ll * ans * a % p;
		a = 1ll * a * a % p;
		b >>= 1;
	}
	return ans;
}

int f(int p) {
	if(p == 1) return 0;
	int x = phi(p);
	return qp(2, f(x) + x, p);
}

int main()
{
	int T = 1; scanf("%d", &T);
	while(T--) {
		int p; scanf("%d", &p);
		printf("%d\n", f(p));
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_43900869/article/details/107513111
今日推荐