第一行——咕咕咕。
第二行——我好喜欢数学啊(只是她不喜欢我)(委屈.jpg)
公式是很好推出来的,我们比赛时读了下题想了想就解出了公式:(b个a),然后死在了降幂上。难受啊,明明公式是对的我们也会普通的欧拉降幂就是降不出来啊!
以下为正文:
欧拉定理:在数论中,欧拉定理,(也称费马-欧拉定理)是一个关于同余的性质。欧拉定理表明,若n,a为正整数,且n,a互质,则:。(来自百度百科)
欧拉降幂:由此,我们可以得到降幂公式(a,b,p为任意的正整数):
由此,我们可以延申一下,①对于b个a的a次幂的幂,先将a作底数,b-1个a的a次幂的幂作指数,为模数,对该指数进行降幂②对该指数进行降幂的过程中,我们可以把a作底数,b-2个a的a次幂的幂作指数,
为新的模值,对新指数进行降幂……依次递归降幂,直至降至模值为1(因为任何数模1都为0,指数即可降为0了)。
但以上只是欧拉降幂,这道题的重点是,因为次方不一定无限,所以不能直接套用公式(无法判断b和的大小啊)。
搜了好多题解,没有一个详细讲的qwq我也不是很明白qwq主要是大家都不讲为啥就能判断了qwq(可能对于dalao来说太简单没必要写叭)
所以我决定把它当成个板子来写 所以我决定把结论记住 所以我决定先留个坑慢慢啃懂
第一种方法:
当次数大于3时,只有 a=2a=2 可能小于 φ(p)φ(p),特判一下就好了。(来自这里)
所以我决定记住这句话,然后特判一下qwq
第二种方法:
重写取模函数。(来自这里)
附题目链接:B.super_log
下附代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define ll long long
const ll maxn = 1000005;
using namespace std;
ll pr[maxn];
ll ph[maxn];
bool vis[maxn] = {0};
int tot = 0;
void Eu()
{
ph[0] = 0,ph[1] = 1;
vis[0] = 1,vis[1] = 1;
for(int i = 2; i < maxn; ++i)
{
if(!vis[i])
pr[tot++] = i,ph[i] = i-1;
for(int j = 0; j < tot; ++j)
{
if(i*pr[j] > maxn)
break;
vis[i*pr[j]] = 1;
if(i%pr[j] == 0)
{
ph[i*pr[j]] = ph[i]*pr[j];
break;
}
else
ph[i*pr[j]] = ph[i]*(pr[j]-1);
}
}
}
ll mod(ll x, ll y)
{
return x<y?x:x%y+y;
}
ll po(ll a,ll b,ll m)
{
ll ans = 1;
while(b)
{
if(b&1)
ans *= a,ans = mod(ans,m);
a *= a;
a = mod(a,m);
b >>= 1;
}
return ans;
}
ll res(ll a,ll b,ll m)
{
if(b == 0) return 1;
if(b == 1) return a;
if(m == 1) return m;
ll ans = res(a,b-1,ph[m]);
return po(a,ans,m);
}
int main()
{
Eu();
int t;
scanf("%d",&t);
while(t--)
{
ll a,b,m;
scanf("%lld%lld%lld",&a,&b,&m);
printf("%lld\n",res(a,b,m)%m);
}
return 0;
}