欧拉降幂公式
今天补了一题codeforces 907 的 F 题,看了题解才知道有这个东西(欧拉降幂公式)
我觉我要说的都在代码里了,如果还有啥不理解的,可以看看大佬的博客:https://www.cnblogs.com/ACMLCZH/p/8117161.html
#include<bits/stdc++.h> #define de(x) cout<<#x<<"="<<x<<endl; #define dd(x) cout<<#x<<"="<<x<<" "; #define rep(i,a,b) for(int i=a;i<(b);++i) #define repd(i,a,b) for(int i=a;i>=(b);--i) #define mt(a,b) memset(a,b,sizeof(a)) #define fi first #define se second #define inf 0x7f #define pii pair<int,int> #define pdd pair<double,double> #define pdi pair<double,int> #define mp(u,v) make_pair(u,v) #define sz(a) a.size() #define ull unsigned long long #define ll long long #define pb push_back #define PI acos(-1.0) const int maxn = 1e5+5; const double EPS = 1e-6; using namespace std; map<ll,ll> mp; ll a[maxn]; int mod(ll x,int p){//欧拉降幂公式的取模方法 return x>=p?x%p+p:x; } ll kpow(ll a,ll b,ll p){ //符合欧拉降幂公式的快速幂 ll ret = 1; while(b){ if(b&1) ret = mod(ret*a,p); b >>= 1; a = mod(a*a,p); } return ret; } ll phi(ll k){//求解欧拉函数(他的意思就是比k小且和k互质的数字的个数) ll s=k,kk=k; if(mp.count(k)) return mp[k]; for(ll i=2;i*i<=k;i++){ if(k%i==0) s=s/i*(i-1); while(k%i==0) k/=i; } if(k>1) s=s/k*(k-1); return mp[kk]=s; } ll solve(int l,int r,ll p){ //递归求解,最多logp次,因为phi(p)最慢的话就是log次能到1,那么到一的话,就直接可以返回a[l]%p+p,因为任何数字mod 1都是零 if( l == r || p == 1 ) return mod(a[l],p); return kpow(a[l],solve(l+1,r,phi(p)),p); } int main() { int n,q; ll p; scanf("%d%lld",&n,&p); rep(i,1,n+1) scanf("%lld",&a[i]); scanf("%d",&q); int l,r; rep(i,0,q){ scanf("%d%d",&l,&r); printf("%lld\n",solve(l,r,p)%p); } return 0; }
posted on 2017-12-30 18:15 chinacwj1 阅读(1261) 评论(0) 编辑 收藏 举报