Luogu[P4139] 上帝与集合的正确用法(扩展欧拉定理)

一句话题面

求 $ 2{2{2^{...}}} \ $ \(mod\) $p $

题解

首先我们要知道什么是扩展欧拉定理:

如果\(b ≥ \varphi(p)\)

\(a^b \equiv a^{b \ mod \ \varphi(p)\ +\ \varphi(p)} (mod \ p)\)

可以发现,在这道题中\(a=2\),\(b=2^{2^{2^{...}}}\)

然后我们发现$ 2{2{2^{...}}} $ 这玩意是 $ ≥ \varphi(p) $ 的

然后我们知道\(\varphi(1) = 1\)

这就很好办了,我们线性筛出\(\varphi(i)\),递归快速幂求\(a^{b \ mod \ \varphi(p)\ +\ \varphi(p)} (mod \ p)\)

于是这道题就可以愉快的AC了。

代码展示


#include<bits/stdc++.h>
#define Maxl 10000007
#define Maxn 100005
using namespace std;
int tot,prime[Maxl],check[Maxl],phi[Maxl],m;
int PowerMod(long long a, int n, int mod,int c = 1) {for (; n; n >>= 1, a = a * a % mod) if (n & 1) c = c * a % mod; return c;}//快速幂
int dfs(int x)
{
	if (x == 1) return 0;
	return PowerMod(2,dfs(phi[x]) + phi[x],x);//递归
}
signed main(){
	for (int i = 2; i <= Maxl; i++)
	{
		if (!check[i])
		{
		  prime[tot++] = i;
		  phi[i] = i - 1;
	    }
		for (int j = 0; j < tot; j++)
		{
			if (i * prime[j] > Maxl)
			  break;
		    check[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);  //积性函数的定义
		}
	}//线性筛
	scanf("%d",&m);
	while (m--)
	{
		int p;
		scanf("%d",&p);
		printf("%d\n",dfs(p));
	}
} 

posted @ 2018-12-22 14:05  taoyc  阅读(155)  评论(0编辑  收藏  举报