Luogu P5091 欧拉定理&&CF17D Notepad

P5091

题意

链接
\(a^b \bmod p\),\(b \le 10^{20000000}\)

Idea

这是个模板题,
使用扩展欧拉定理
\[a^b =\begin{cases} a^b,b<phi(p)\\a^{b \bmod phi(p) + phi(p)},b \ge phi(p) \end{cases}\]
上面的操作又称欧拉降幂

证明

见下篇

Code

int phi[maxn],prime[maxn],f[maxn];
char s[20000010];
inline int power(int a,int b,int p){
    int ans=1%p;
    for(;b;b>>=1){
        if(b&1) ans=ans*a%p;
        a=a*a%p;
    }
    return ans;
}
inline void init(int x){
    int t=0;
    phi[1]=1;
    for(int i=1;i<=x;i++){
        if(!phi[i]) phi[i]=i-1,prime[++t]=i;
        for(int j=1;j<=t&&i*prime[j]<=x;j++){
            if(!(i%prime[j])){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            phi[i*prime[j]]=phi[i]*phi[prime[j]];
        }
    }
}
signed main(){
    int n=read(),p=read();
    init(p);
    scanf("%s",s+1);
    int len=strlen(s+1),d=0;
    int tmp=0; bool book=1;
    for(int i=1;i<=len;i++){
        d=(d*10+(s[i]-48))%phi[p];
        tmp=(tmp*10+(s[i]-48));
        if(tmp>phi[p]) book=0;
    }
    int ans=power(n,book?tmp:d+phi[p],p);
    printf("%d",ans);
    return 0;
}

CF17D Notepad

题意

Luogu的
CF的
有个本子,往本子上写全部长度为\(n\)\(b\)进制数,每页可以写\(c\)个。
要求数字要求所有数字必须严格不含前导0。求最后一页上有多少个数字。

Idea

考虑第一位不能为0,只能有\(b-1([1,b-1])\)种填法
考虑后\(n-1\)位可以填\([0,b-1]\),则有\(b^{n-1}\)种填法
则显然\(ans=(b-1)\times b^{n-1} \bmod c\)
\(ans=0\) ,则答案为\(p\),因为不用翻开下一页
如何求\(ans\)呢?
欧拉降幂即可。

Code

inline int power(int a,int b,int p){
    int ans=1%p;
    for(;b;b>>=1){
        if(b&1) ans=ans*a%p;
        a=a*a%p;
    }
    return ans;
}
inline int phi(int x){
    int t=x,tot=x;
    for(int i=2;i*i<=t;i++)
    if(!(x%i)){
        tot=tot/i*(i-1);
        while(!(x%i)) x/=i;
    }
    return x>1?tot/x*(x-1):tot;
}
char s1[maxn],s2[maxn];
int b[maxn],p;
signed main(){
    scanf("%s %s %d",s1+1,s2+1,&p);
    int len1=strlen(s1+1),len2=strlen(s2+1);
    int d1=0,d2=0,Phi=phi(p);
    for(int i=1;i<=len1;i++) d1=(d1*10+(s1[i]-48))%p;
    for(int i=1;i<=len2;i++) b[i]=s2[i]-48;
    b[len2]--;
    for(int i=len2;i;i--)
    if(b[i]<0) b[i]+=10,b[i-1]--;
    else break;
    int tmp=0; bool book=1;
    for(int i=1;i<=len2;i++){
        d2=(d2*10+b[i])%Phi;
        tmp=tmp*10+b[i];
        if(tmp>=Phi) book=0; 
    }
    int ans=(d1+p-1)%p*power(d1,book?tmp:d2+Phi,p)%p;
    printf("%d",!ans?p:ans);
    return 0;
}

\(\text{浮生若梦,为欢几何,不如许一个安然无忧}\)

转载于:https://www.cnblogs.com/cbyyc/p/11545549.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值