莫名其妙的欧拉降幂定理,网上也找不到证明和解释,只有这个看不太懂(感觉代码和文字关联不大)的博客,但是神奇的可以ac,觉得很奇怪,难道真的是我太菜了。。。
代码应该是正确的,虽然很多地方没法理解,但是可以记录下来当模板使用
博客中的代码:
#include<bits/stdc++.h> #define Mod(a,b) a<b?a:a%b+b //重定义取模,按照欧拉定理的条件 #define LL long long #define N 100010 using namespace std; LL n,q,mod,a[N]; map<LL,LL> mp; LL qpow(LL x,LL n,LL mod) { LL res=1; while(n) { if (n&1) res=Mod(res*x,mod),n--; x=Mod(x*x,mod); n>>=1; } return res; } LL phi(LL k) { LL i,s=k,x=k; if (mp.count(k)) return mp[x]; //记忆化存储 for(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); mp[x]=s; return s; } LL solve(LL l,LL r,LL mod) { if (l==r||mod==1) return Mod(a[l],mod); //如果到右端点或者φ值等于1,那么直接返回当前数字 return qpow(a[l],solve(l+1,r,phi(mod)),mod); //否则指数为[l+1,r]区间的结果 } int main() { scanf("%lld%lld",&n,&mod); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); scanf("%lld",&q); while(q--) { int L,R; scanf("%d%d",&L,&R); printf("%lld\n",solve(L,R,mod)%mod); //对mod取模,因为qpow内部是用Mod(a,b)取模 } return 0; }其中有一段代码:
LL phi(LL k) { LL i,s=k,x=k; if (mp.count(k)) return mp[x]; //记忆化存储 for(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); mp[x]=s; return s; }
返回值是欧拉函数值,一开始有点懵,仔细一看就是唯一分解定理
将一个数分解,各种质因子,然后运用欧拉函数求解方式
φ(n)=n*(1-1/p1)(1-1/p2)....(1-1/pk),其中p1、p2…pk为n的所有素因子,可以求得欧拉函数值,值得学习。。上面的代码就当模板用吧先。。