Codeforces 906D(欧拉降幂定理? + 唯一分解定理)

莫名其妙的欧拉降幂定理,网上也找不到证明和解释,只有这个博客,但是神奇的可以ac,不知道快速幂为什么写成这个样子,正常的快速幂还要wa,觉得很奇怪,真的是我太菜了。。。

刚刚突然想明白了快速幂为什么写成这个样子。。。刚才自己好傻还想了半天,写成这个样就是普通的快速幂,不过是符合题目要求而已。。。(将一个数的次方换成欧拉降幂定理之后的形式)
φ = 1 的时候也很好理解,此时等号右边的平方是确定值即 1 ,此时递归可以结束,返回值为L

//代码应该是正确的,虽然没法理解,但是可以记录下来当模板使用
博客中的代码:
#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的所有素因子,可以求得欧拉函数值,值得学习。。上面的代码就当模板用吧先。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值