拓展欧拉定理浅谈

前置芝士——欧拉定理:

若正整数\(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\times a_i\equiv~a\times a_j~(mod~n)\),则\(a\times(a_i-a_j)\equiv~0~(mod~n)\),又因为\(a\)\(n\)互质,所以\(a_i-a_j\equiv0\),即\(a_i\equiv~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)\)时,最常用的应该就是快速幂了吧?但,如果\(b\le10^{100}\)呢?如果\(b\le10^{20000000}\)呢(见模板)?

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

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

它大概分以下三种情况

\[a^b\equiv\left\{\begin{aligned}a^{b\%\phi(n)}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\gcd(a,n)=1\\a^b~~~~~~~~~~~~~~~~~~~\gcd(a,n)\neq1\&b<\phi(n)\\a^{b\%\phi(n)+\phi(n)}~~~~\gcd(a,n)\neq1\&b\ge\phi(n)\end{aligned}\right. \]

第一种情况:

证明:

\(b=q\times\phi(n)+r\),其中\(0\le r<\phi(n)\),即\(r=b\mod\phi(n)\)

故:

\[a^b\equiv a^{q\times\phi(n)+r}\equiv (a^{\phi(n)})^q\times a^r\equiv1^q\times a^r\equiv a^{b\mod\phi(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\n",print(p));
	}
	return 0;
}

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

posted @ 2020-08-28 08:08  Chester1011  阅读(250)  评论(0编辑  收藏  举报
/*simplememory*/