题目链接:https://nanti.jisuanke.com/t/41299
题目:
题意:
给定a,b,m
求(b个a)
解题历程:
提炼出式子之后直接快速幂暴力了,显然是不对的,幂次取过模了需要用到欧拉降幂
(mod p)
网络赛时打出锅了,网络赛后期脑子不清醒了,绕坑能力--,代码没存,赛后重打一次就过了,丝毫没有印象锅出在哪里555。
模板存住省得下次再踩坑。
题解:
1. O(n)线性筛预处理欧拉函数,phi[ 1 ] = 1
2. 对于欧拉降幂的dfs,坑点:
(1)如果不判断mod == 1,会多递归很多层直接tle
(2)注意flag和flag1的区分,两者不是同一个,flag是传给下一层的,flag1是上一层传过来,用于本层判断 b 和 phi[ p ] 的关系的
(3)mod == 1时flag = 1
3. 对于快速幂,坑点:
(1)判断中间所有乘的过程是否大于等于mod
(2)mi == 1跳出,因为这里的di不会再对ans有影响,大于等于mod也与结果无关,否则会wa
(3)循环外ans %= mod是为了填mi = 0,mod = 1时的坑
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 +5;
int vis[maxn],prime[maxn],phi[maxn];
void init()
{
int tot = 0;
phi[1] = 1;
for (int i = 2; i < maxn; i ++)
{
if (!vis[i])
{
prime[tot++] = i;
phi[i] = i - 1;
}
vis[i] = 1;
for (int j = 0; j < tot; j ++)
{
if(1ll * prime[j] * i >= maxn)break;
vis[prime[j] * i] = 1;
if (i % prime[j])
phi[prime[j] * i] = phi[i] * (prime[j] - 1);
else
{
phi[prime[j] * i] = phi[i] * prime[j];
break;
}
}
}
}
ll quickpow(ll di,ll mi,ll mod,int &flag)
{
ll ans = 1;
while(mi)
{
if(mi & 1)
{
ans = ans * di;
if(ans >= mod)flag = 1;
ans %= mod;
}
if(mi == 1)break;
di = di * di;
if(di >= mod)flag = 1;
di %= mod;
mi >>= 1;
}
if(ans >= mod)flag = 1;
ans = ans % mod;
return ans;
}
ll dfs(int a,int b,int mod,int &flag)
{
int flag1 = 0;
if(!b)
{
if (1 >= mod)flag = 1;
return 1 % mod;
}
if(mod == 1)
{
flag = 1;
return 0;
}
ll tmp = dfs(a,b - 1,phi[mod],flag1);
if(flag1)
return quickpow(a,tmp + phi[mod],mod,flag);
return quickpow(a,tmp,mod,flag);
}
int main()
{
int t;
scanf("%d",&t);
init();
while(t --)
{
int a,b,mod;
scanf("%d%d%d",&a,&b,&mod);
int flag = 0;
printf("%lld\n",dfs(a,b,mod,flag));
}
return 0;
}