码迷,mamicode.com
首页 > 其他好文 > 详细

[扩展欧拉定理例题]降幂大法

时间:2019-12-21 15:35:53      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:ddl   set   lld   hide   ec2   最小   break   line   图片   

降幂大法1

题面:

   给出a,b,p,计算a^b %p 的结果,0< a <= 10^9,0< b <= 10^10000,0< p <= 10^9。

思路:

  10的10000次方,这题不简单。那么经过欧拉定理的学习之后,有如下结论:技术图片,其中a,n互质,但是很显然,他不能用来解决这道题。那么扩展欧拉定理应运而生了。

  acacmodφ(m)+φ(m)(mod m)

  其中c>=φ(m)。他很强,强到了一种逆天的程度。对于这个定理,我有一个优雅的证明,但是在网上打不出来。又及,c<φ(m)的时候直接快速幂。

  回到这道题,这道题无非就是用扩展欧拉定理去解决它,虽然它的p在后面很恶心。

  先把所有的东西读进来,处理好φ(p),再对指数进行类似于快读的处理。由于快读只涉及到加和乘,完全可以一边算一遍%φ(p)。

技术图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<fstream>
using namespace std;
#define ll long long
ll a,b,p,mod;
char s[100005];
ll phi(int n){
    ll ans=n;
    for(int 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;
}
long long KSM(ll a,ll b){
    ll sp=1;
    while(b){
        if(b&1)sp*=a;
        sp%=p;
        b>>=1;
        a=a*a;
        a%=p;
    }
    return sp;
}
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    scanf("%lld%s%lld",&a,s,&p);
    int len=strlen(s);
    mod=phi(p);
    int flag=0;
    for(int i=0;i<len;++i){
        b=b*10+(s[i]-0);
        if(b>=mod)flag=1;
        b%=mod;
    }
    if(flag)b+=mod;
    cout<<KSM(a,b)%p<<endl;
    return 0;
}
View Code

降幂大法2

题面:

  技术图片

思路:

  禁止套娃!!是的,看到省略号的时候我就直接懵了。你管这个叫题?分明就是俄罗斯套娃。

  但是是套娃,又有答案,那他就不是无限套娃(世 界 崩 坏)。见过俄罗斯套娃的都知道,套娃必然会有一个最小的,此题个关键就在于找出最小的套娃。

  由扩展欧拉定理可以知道,一个数膜另外一个数,这个任务可以甩给他的指数。指数又甩给它的指数,这就是套娃。于是这样我们可以设计一个函数,先令T=22...他的任务是解决T%p的问题,于是无限递归处理,然后p在不断地phi,phi,phi,phi...直到φ(p)=1,那么很显然的,一个数%1=0.套娃结束。最小的娃找到了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<fstream>
using namespace std;
#define ll long long
ll a,b,p;
char s[100005];
ll phi(int n){
    ll ans=n;
    for(int 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;
}
long long KSM(ll a,ll b,ll mod){
    ll sp=1;
    while(b){
        if(b&1)sp*=a;
        sp%=mod;
        b>>=1;
        a=a*a;
        a%=mod;
    }
    return sp;
}
int solve(int p){
    int k=phi(p);
    if(k==1)return 0;
    return KSM(2,(solve(k)+k),p);
}
int main(){
    while(scanf("%lld",&p)!=EOF){
        cout<<solve(p)<<endl;
    }
    return 0;
}

[扩展欧拉定理例题]降幂大法

标签:ddl   set   lld   hide   ec2   最小   break   line   图片   

原文地址:https://www.cnblogs.com/clockwhite/p/12076852.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!