数的阶乘幂 && 洛谷 U132839 幂(数学,快速幂)
传送门
解题思路
先看一下数据范围,a、b、c都是10^6,所以大体推断出做法时间复杂度约为nlogn。
根据axy=(ax)^y,所以ab!=(((((a^1)^2)^3)^4)^……)^b。
用底数变化的快速幂(O(logb))做b次即可。
或者对指数b!做一些处理——
我们知道指数b!一定不能直接mod,但是我们把b! mod一个x,使得结果不变。
其中x要保证axmod c=1。很显然,这样做就等于把b!-kx,等于ab!/akx,结果不变。
怎么保证一定有这个x呢?
我们把a1,a2,a3……ac %c写出来
- 当存在一个x使得ax%c=0时,只需判断b!是否大于等于x,若大于等于,结果为0,否则结果直接快速幂算即可。
- 若不存在x使得ax%c=0,那么我们不妨设不存在ax%c=1,即ak%c ε [2,c-1](k:1~c)。那么一定存在两个数s和t(s>t),as%c=at%c。那么很显然,as-t%c=1。这与假设相违背,所以一定存在这个x。
所以这两种做法都可以过此题,第一种O(nlogn),第二种O(n)。
另外看60分做法,模数是质数,我们可以想到费马小定理——ap-1%p=1,这时,c-1即是我们要找的x。
AC代码(第一种做法)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 long long a,b,c; 7 long long kuaisumi(long long a,int x){ 8 if(x==1) return a%c; 9 long long ans; 10 if(x&1) ans=a%c; 11 else ans=1; 12 long long kkk=kuaisumi(a,x/2); 13 ans=ans*kkk%c*kkk%c; 14 return ans; 15 } 16 long long work(long long a,long long b){ 17 while(b>0){ 18 a=kuaisumi(a,b); 19 b--; 20 } 21 return a%c; 22 } 23 int main(){ 24 cin>>a>>b>>c; 25 cout<<work(a,b)%c<<endl; 26 return 0; 27 }