前置知識:
歐拉篩,一些基本數論知識。
簡要題意:
求 .
.
首先,看到這個數據範圍你就發現你涼涼了。
算法一
一個簡單的弱化:
.
顯然你 過了。
算法二
一個再簡單點的強化呢:
. .
你用 可以飛快過了 。
算法三
那麼考慮這道題目呢?不行了吧?
可能, 的樸素快速冪 每次 的高精度除法 一定卡常是可以通過的。
但是我們不要,我們只需要用一個簡單的定理:
先不管如何證明,考慮用這個玩意兒怎麼做。
用 的時間可以算出 ,然後快讀 , 則套公式快速冪,如果 只能說明 也很小,再跑一個 也沒啥問題了。
具體證明大家可以去看一下 的博客
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){char ch=getchar(); int f=1; while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0; while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f;}
inline int remo(int m) {
char c; while(!isdigit(c=getchar()));
int x=0; bool f=0;
for(;isdigit(c);c=getchar()) {
x=x*10+c-'0';
if(x>=m) f=1,x%=m;
} return f?(x+m):x;
}
inline void write(int x) {
if(x<0) {putchar('-');write(-x);return;}
if(x<10) {putchar(char(x%10+'0'));return;}
write(x/10);putchar(char(x%10+'0'));
}
inline int pw(int a,int b,int m) {
int ans=1; while(b) {
if(b&1) ans=ans*a%m;
a=a*a%m; b>>=1;
} return ans;
}
signed main() {
int a=read(),m=read(); a%=m;
int phi=1,t=m,ans=1;
for(int i=2;i*i<=t;i++) {
if(t%i) continue;
phi*=i-1; t/=i;
while(t%i==0) phi*=i,t/=i;
} if(t>1) phi*=t-1; //printf("%d\n",remo(phi));
printf("%d\n",pw(a,remo(phi),m));
return 0;
}