拓展欧拉定理浅谈

前置芝士——欧拉定理:

若正整数(a,n)互质,则(a^{phi(n)}equiv1~(mod~n)),其中(phi(n))为欧拉函数

证明:

设小于(n)且与(n)互质的数构成的集合(即简化剩余系)为{(a_1,a_2,a_3...a_{phi(n)})},对于(forall a_i,a_j),若(a_i,a_j)在同一同余类时,有(~a imes a_iequiv~a imes a_j~(mod~n)),则(a imes(a_i-a_j)equiv~0~(mod~n)),又因为(a)(n)互质,所以(a_i-a_jequiv0),即(a_iequiv~a_i)。因此,当(a_i)(a_j)不在同一同余类时,(a!a_i,a!a_j) 也在不同的同余类。

又因为简化剩余系关于模(n)乘法封闭,故(a!a_i,a!a_j)也在这个简化剩余系中。因此,集合{(a_1,a_2...a_{phi(n)})}和集合{({a!a_1,a!a_2...a!a_{phi(n)}})}都可以表示(n)的简化剩余系,因此:

[a^{phi(n)}a_1a_2...a_{phi(n)}equiv(a!a_1)(a!a_2)...(a!a_{phi(n)})~(mod~n) ]

[Rightarrow~a^{phi(n)}a_1a_2...a_{phi(n)}equiv~a_1a_2...a_{phi(n)}~(mod~n) ]

[Rightarrow a^{phi(n)}equiv~1~(mod~n) ]

证毕


正题:拓展欧拉定理

当我们求(a^b(mod~p))时,最常用的应该就是快速幂了吧?但,如果(ble10^{100})呢?如果(ble10^{20000000})呢(见模板)?

这个时候,不仅(long~long)不够,快速幂也不够了。。

所以,又一个神奇的定理出现了!

它大概分以下三种情况

[a^bequivleft{egin{aligned}a^{b\%phi(n)}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~gcd(a,n)=1\a^b~~~~~~~~~~~~~~~~~~~gcd(a,n) eq1&b<phi(n)\a^{b\%phi(n)+phi(n)}~~~~gcd(a,n) eq1&bgephi(n)end{aligned} ight. ]

第一种情况:

证明:

(b=q imesphi(n)+r),其中(0le r<phi(n)),即(r=bmodphi(n))

故:

[a^bequiv a^{q imesphi(n)+r}equiv (a^{phi(n)})^q imes a^requiv1^q imes a^requiv a^{bmodphi(n)} ]

证毕

第二种情况:废话

第三种情况:咕咕咕~~ (有能力的读者可以自己证明啦 (就是我不会)

有一个公理说明:这东西你虽然不知道它怎么来的,但知道怎么用就行。


OK,咱们来实践,上例题!

例题:P4139 上帝与集合的正确用法

一句话题意:(2^{2^{2...}}\%~p)

都不需要怎么引入了,看到的第一眼就知道是个拓展欧拉定理,但问题是如何求(2^{2^{2...}}\%~phi(p)+phi(p))

但你们观察这个式子(2^{2^{2...}}\%~phi(p)+phi(p)),把中间的(2^{2^{2...}}\%~phi(p))拿出来,把它看作一个整体,又变成了(2^{2^{2...}}\%~p).

然后我们就可以递归直到(p)变为(0),再每次加回(phi(p)),就A了。

所以先用线性筛预处理出所有的(phi(p)),然后递归,本题就完事了。。

手起,码落

#include<bits/stdc++.h>
#define re register
using namespace std;
const int N=1e7+5;
int E[N],T;
void euler(int MAXN)  
{  
	E[1]=1;
    for(int i=2;i<=MAXN;i++)
	{  
        if(!E[i])
        for(int j=i;j<=MAXN;j+=i)
		{  
            if(!E[j])E[j]=j;
            E[j]=E[j]/i*(i-1);
        }  
    }  
}
inline int Pow(int x,int y,int mod)
{
	re int sum=1;
	for(;y;y>>=1,x=(1ll*x*x)%mod)
		if(y&1)sum=(1ll*sum*x)%mod;
	return sum;
}
inline int print(int x)
{
	if(x==1)return 0;
	return Pow(2,print(E[x])+E[x],x);
}
int main()
{
	re int p;
	euler(N-5);
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&p);
		printf("%d
",print(p));
	}
	return 0;
}

都看到这了,给个赞不!QWQ~

原文地址:https://www.cnblogs.com/jkzcr01-QAQ/p/13575203.html