Exponial

题目地址https://vjudge.net/contest/236648#problem/G。

这题的关键就是要用到欧拉定理降幂,欧拉定理就是 a^(φ(m))同余1(mod m) (a与m互质)

其中φ(m)为欧拉函数,具体运算方法为 设n=(p1^a1)*(p2^a2)*……*(pk^ak) (为N的分解式)  那么φ(n)=n*(1-1/p1)*(1-1/p2)*……*(1-1/pk)。

代码如下:

long long Euler(long long n)
{
    long long res=n,ans=n;
    for (int i=2;i*i<=ans;i++)//类似于筛法
    {
        if (ans%i==0)
        {
            res=res/i*(i-1);//先除后乘防止溢出
            while (ans%i==0)
            {
                ans/=i;
            }
        }
    }
    if (ans>1) res=res/ans*(ans-1);//ans为质数的情况
    return res;
}

但由于欧拉定理要求a,m互质,而题目中的情况可能是不互质的,这时要使用扩展的欧拉定理,

a^{x} \equiv a^{x\bmod \varphi{(m)} + \varphi{(m)}} \pmod{m},其中a为任意整数,x,m为正整数,并且x\geq \varphi(m)(注意这里a和m不一定互素)

证明见https://zhuanlan.zhihu.com/p/24902174 。

这时只要保证x\geq \varphi(m)就可以了,又因为φ(m)<m<=1E9,而exponial(5) ≈ 6.206 ⋅ 10E183230远远大于10E9,所以当n>5时就可以安心用上述公式了。

通过代码如下:

#include<cstdio>

long long Euler(long long n)
{
    long long res=n,ans=n;
    for (int i=2;i*i<=ans;i++)
    {
        if (ans%i==0)
        {
            res=res/i*(i-1);
            while (ans%i==0)
            {
                ans/=i;
            }
        }
    }
    if (ans>1) res=res/ans*(ans-1);
    return res;
}

long long pow(long long n,long long p,long long m)
{
    long long res=1,x=n;
    while (p)
    {
        if (p&1) res=(res*x)%m;
        x=(x*x)%m;
        p>>=1;
    }
    return res;
}

long long result(long long n,long long m)
{
    if (m==1) return 0;//为什么不加就会超时 (100000 1)
    if (n==1) return 1%m;
    if (n==2) return 2%m;
    if (n==3) return 9%m;
    if (n==4) return 262144%m;
    long long tmp=Euler(m);
    return pow(n,result(n-1,tmp)+tmp,m);
}

int main()
{
    int n,m;
    while (scanf("%d %d",&n,&m)==2 &&n &&m)
    {
        printf("%d\n",result(n,m));
    }
    return 0;
}

仍然存在的两个问题:

1、实际上在通过代码中,n=5的情况没有考虑,此时x=exponial(4)=262144,而如果m取100000007,

φ(m)=100000006>x,不满足条件。

2、在result 函数中如果不加 if (m==1) return 0 会超时,但不明白为什么会这样。

希望有大佬们能帮忙解决。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值