扩展欧拉定理

扩展欧拉定理

前置芝士

欧拉定理

定义

对于a与m不一定互质的情况,有:

[a^c~equiv~egin{cases}a^{cmodvarphi(m)} &gcd(a,m)~=~1 \a^c &gcd(a,m)~ eq~1~且~c~<~varphi(m) \ a^{cmodvarphi(m)+varphi(m)}&gcd(a,m)~ ot=~1~且~c~>=~varphi(m)end{cases} ]

推论

(m=1) 时明显成立,接下来讨论 (m ot=1) 的情况。

对于 (gcd(a,m)=1) 的情况,因为 (a^{varphi(m)}equiv 1pmod m) ,所以每 (varphi(m))(a) 就相当于乘 (1) 。于是只需要算

(cmodvarphi(m)) 次。

对于 (c<varphi(m)) 的情况,直接爆算

下面证明第三种情况。

先证明 (a) 是一个质数的情况:

引理1

(forall p) 为质数,(rin Z^+) ,都有 (varphi(p^r)=(p-1) imes p^{r-1})

证明:

由于p是一个质数,所以 (1sim (p^r-1)) 中有且仅有 (i imes p,iin (0,p^{r-1}))(p^r) 不互质。

于是 (varphi(p^r)=p^r-p^{r-1}=p^{r-1} imes (p-1))

证毕
引理2

(forall~kin Z)(exists~a,b,x,yin Z^+,x^a imes y^b=k) ,都有 (a,bleqvarphi(k))

证明

先考虑k为一个质数p的r次幂的情况。根据引理1有:

[varphi(k)=varphi(p^r)=(p-1) imes p^{r-1} ]

下面说明 ((p-1) imes p^{r-1}geq r)

当p=2时:

经验证(~r=1,2,3~)时成立。当(~r>3~)时按照r的大小做数学归纳,可证正确性。

(~p~>~2~)时,不等号左侧增大,右侧不变,不等式仍然成立。

考虑k是多个质数幂时的情况,按照质数个数做数学归纳,正确性成立。

任意组合质数,引理得证。

证毕
引理三:

(exists~r~leq~c~,a^{varphi(m)+r}~equiv~a^rpmod m。)

证明:

(m=t imes a^r) ,其中 (gcd(t,a)=1) ,t的存在性显然

因为 (gcd(t,a)=1) ,且 (varphi) 函数是一个积性函数,所以 (varphi(t)|varphi(m))

根据欧拉定理,(a^{varphi(t)}~equiv~1~pmod t) ,于是:

[a^{varphi(m)}~equiv~1~pmod t ]

同余式同乘 (a^r) ,于是:

[a^{varphi(m)+r}~equiv~a^r~pmod m ]

已经证明可以构造出这样的r。根据引理2,(r~leq~varphi(m))。又 (c~geq~varphi(m)),于是可证构造出的(r~leq~c)。定理得证。

证毕

于是:

[a^c~equiv~a^{c-r+r}~equiv~a^{c-r+varphi(m)+r}~equiv~a^{c+varphi(m)}~pmod m ]

对上式做数学归纳,可得(a^c~equiv~a^{c+kvarphi(m)}~,~k~in~Z),需保证指数为正。

于是最小的合法的指数即为(cmodvarphi(m)~+~varphi(m))

于是有:

[a^c~equiv~a^{c~mod~varphi(m)~+~varphi(m)}pmod m ]

当a是一个质数的幂次时,设 (a=p^k) ,则

[a^cequiv p^{ck}equiv p^{ck+varphi(m)}equiv p^{ck+kvarphi(m)}equiv (p^k)^{c+varphi(m)}equiv (p^k)^{cmodvarphi(m)+varphi(m)} pmod m ]

当a时多个质数次幂的乘积时,依据唯一分解定理做数学归纳,即证正确性。证毕。

代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll a,m,b;

inline ll read(ll m){
	register ll x=0,f=0;char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)){
		x=x*10+ch-'0';
		if(x>=m) f=1;
		x%=m;ch=getchar();
	}
	return x+(f==1?m:0);
}

ll phi(ll n){
	ll ans=n,m=sqrt(n);
	for(ll i=2;i<=m;i++){
		if(n%i==0){
			ans=ans/i*(i-1);
			while(n%i==0) n/=i;	
		}
	}
	if(n>1) ans=ans/n*(n-1);
	return ans;
}

ll fast_pow(ll a,ll b,ll p){
	ll ret=1;
	for(;b;b>>=1,a=a*a%p)
		if(b&1) ret=ret*a%p;
	return ret;
}

int main()
{
    scanf("%lld%lld",&a,&m);
    b=read(phi(m));
    printf("%lld
",fast_pow(a,b,m));
    return 0;
}

例题

CF17D Notepad

思路

这道题的范围是 (2leq aleq 10^{1000,000})(1leq nleq 10^{1000,000})(1leq pleq 10^9)

一个(a)进制的数字的每一位有(a)种取值,但是题目要求不能有前导0,所以第一位只有(a-1)种取值。

所以满足要求的(a)进制数有 ((a-1)a^{n-1}) 个。

所以题目要求我们求得就是

[(a-1)a^{n-1}mod p ]

(但是当 (p|(a-1)a^{n-1}) 时应输出 (p) 。因为此时最后一页有0个字,相当于这一页还没写,也就不是最后一页了)

(a,n) 很大,但是 (pleq 10^9) 。根据扩展欧拉定理,有 (a^{n-1}equiv a^{(n-1)modvarphi(p)+varphi(p)} pmod p) 。所以我们可以边读入边取模。反正 (abmod pequiv(amod p) imes (bmod p)~mod p)

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;

const int N=1000010;
char sa[N],sn[N];
ll p,a,n,phi,q,ans;
int len1,len2;
bool flag;

ll power(ll x,ll k)
{
	ll ans=1;
	for (;k;k>>=1,x=x*x%p)
		if (k&1) ans=ans*x%p;
	return ans;
}

int main()
{
	scanf("%s %s %lld",sa+1,sn+1,&p);
	phi=q=p; len1=strlen(sa+1); len2=strlen(sn+1);
	for (ll i=2;i*i<=q;i++)
		if (!(q%i))
		{
			phi=phi/i*(i-1);
			while (!(q%i)) q/=i;
		}
	if (q>1) phi=phi/q*(q-1);
	for (int i=1;i<=len1;i++)
		a=(a*10+sa[i]-48)%p;
	for (int i=len2;i>=1;i--)  //n-1
		if (sn[i]==48) sn[i]='9';
		else
		{
			sn[i]--;
			break;
		}
	for (int i=1;i<=len2;i++)
	{
		n=n*10+sn[i]-48;
 		if (n>=phi) flag=1;
		n%=phi;
	}
	if (flag) n+=phi;
	ans=((a-1)*power(a,n)%p+p)%p;
	if (ans) printf("%lld",ans);
		else printf("%lld",p);
	return 0;
}
原文地址:https://www.cnblogs.com/jasony/p/13377358.html