歐拉函數加快速冪:
ll phi(ll n) {
ll ans = 1;
for (ll i = 2; i*i <= n; i++) {
if (n%i == 0) {
n /= i;
ans *= i - 1;
while (n%i == 0) {
n /= i;
ans *= i;
}
}
}
if (n > 1) ans *= n - 1;
return ans;
}
ll multiply(ll a, ll b, ll mod)
{
ll ans = 1;
while (b)
{
if (b & 1)
{
ans = ((ans%mod)*(a%mod)) % mod;
b--;
}
b /= 2;
a = ((a%mod)*(a%mod)) % mod;
}
return ans;
}
例題:
題意:
A(m) = mod (1e9+7),m爲2的層數。T組數據(T<=10),每組輸入包含一個m(1<=m<=10)。
分析:
指數會爆long long,所以需要歐拉降冪。需要注意的是,在計算指數的時候也會用到快速冪,此時模數需要迭代。
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ph(ll x)
{
ll ans=x,a=x;
for(ll i=2; i*i<=x; i++)
{
if(a%i==0)
{
ans=ans/i*(i-1);
while(a%i==0)
a/=i;
}
}
if(a>1)
ans=ans/a*(a-1);
return ans;
}
ll quick_pow(ll a,ll b,ll mod)
{
ll ans=1;
while(b)
{
if(b&1)
{
if(a>=b)
ans=(ans*a)%b+b;
else
ans=ans*a;
}
if(a>=b)
a = (a * a)%mod+mod;
else
a=a*a*a;
b>>=1;
}
return ans;
}
ll f(ll p)
{
if(p==1)
return 0;
ll k=ph(p);
return quick_pow(2,f(k)+k,p);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ll p;
scanf("%lld",&p);
printf("%lld\n",f(p));
}
return 0;
}
//計算指數
ll cul(int x, ll p)
{
ll val = 4;
if (x == 1) {
return val;
}
//注意模數需要迭代
val = multiply(2, cul(x - 1, phi(p)), p);
return val % p + p;
}
int main()
{
int T;
scanf("%d", &T);
f[1] = 4;
//phi(1e9+7)=1e9+6
for (int i = 2; i <= 10; i++) {
f[i] = multiply(2, cul(i - 1, MOD - 1), MOD);
}
while (T--)
{
scanf("%d", &n);
printf("%lld\n", f[n]);
}
return 0;
}
那麼再來一題
題意 :AB mod C 其中B爲101000000
思路:B很大,所以需要降冪,套一下公式求一下就行了。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
ll phi(ll n)
{
ll ans=n;
for(ll i=2; i*i<=n; i++)
{
if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0)
n/=i;
}
}
if(n>1)
ans=ans/n*(n-1);
return ans;
}
ll quickpow(ll a,ll b,ll c)
{
a%=c;
ll ans=1;
while(b)
{
if(b&1)
ans=ans*a%c;
a=a*a%c;
b>>=1;
}
return ans;
}
ll a,b,c;
char s[11111];
int main()
{
while(~scanf("%lld %s %lld",&a,s,&c))
{
ll p=phi(c);
int len=strlen(s),flag=0;
b=0;
for(int i=0; i<len; i++)
{
b=b*10+s[i]-'0';
if(b>p)
{
flag=1;
b%=p;
}
}
ll ans;
if(flag)
{
ans=quickpow(a,b+p,c);
}
else
{
ans=quickpow(a,b,c);
}
printf("%lld\n",ans);
}
return 0;
}