[笔记] 欧拉定理

欧拉定理的内容:

\(a>\varphi(m)\)时,\(x^a \equiv x^{(a \ mod \ \varphi(m))+\varphi(m)} \ (mod \ m)\)
\(x和m\)互质时,\(x^{\varphi(m)}\equiv 1\),很多地方讲欧拉定理的时候只有这一条,实际上上面那一条也是欧拉(降幂)定理的内容。

证明:

咕咕咕(建议直接把公式背下来)


例题:

\(x^{x^{x^x \cdots}}\)(无限个x)对\(y\)取模的值,t组数据。

解法:

\(f(x,y)\)表示\(x,y\)的答案,当y为1时,显然答案为0。否则根据欧拉定理:\(x^{x^{x^x \cdots}} \equiv x^{(x^{x^x \cdots} \ mod \ \varphi(y))+\varphi(y)}\ mod \ y\)\(x^{x^x \cdots} \ mod \ \varphi(y)\)可以递归求解,发现最终y一定会变成1从而结束递归。递归次数是\(log(y)\)级别的,因为众所周知对于>2的整数n,\(\varphi(n)\)一定是偶数,所以如果y是奇数,\(\varphi(y)\)一定会是偶数;而如果y是偶数,则\(\varphi(y)\)最多是y的一半(因为至少有一半的数都和y有共同的因数2)。

点击查看代码
#include <bits/stdc++.h>

#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define pii pair <int,int>
#define pb push_back
#define fi first
#define se second
#define mpr make_pair

using namespace std;

LL qpow(LL x,LL a,LL MOD)
{
	LL res=x,ret=1;
	while(a>0)
	{
		if((a&1)==1) ret=ret*res%MOD;
		a>>=1;
		res=res*res%MOD;
	}
	return ret;
}

LL phi[20000010];
bool isp[20000010];
vector <LL> pri;

void sievePhi()
{
  for(LL i=2;i<=20000000;++i) isp[i]=true;
  for(LL i=2;i<=20000000;++i)
  {
    if(isp[i]) pri.pb(i),phi[i]=i-1;
    rep(j,pri.size())
    {
      if(pri[j]*i>20000000) break;
      isp[pri[j]*i]=false;
      if(i%pri[j]!=0) phi[i*pri[j]]=phi[i]*(pri[j]-1);
      else
      {
        phi[i*pri[j]]=phi[i]*pri[j];
        break;
      } 
    }
  }
}

LL t,x,y;

//x^a=x^(a%phi[m]+phi[m]) (%m)
LL dfs(LL xx,LL yy)//xx^xx^xx... %yy
{
  if(yy==1) return 0;
  LL pw=dfs(xx,phi[yy])+phi[yy];
  return qpow(xx,pw,yy);
}

int main()
{
  //freopen("power.in","r",stdin);
  //freopen("power.out","w",stdout);
  sievePhi();
  cin>>t;
  rep(tn,t)
  {
    cin>>x>>y;
    if(x==1) cout<<1%y<<endl;
    else cout<<dfs(x,y)<<endl;
  }
  return 0;
}
posted @ 2022-08-09 21:33  LegendStane  阅读(128)  评论(0)    收藏  举报