The Preliminary Contest for ICPC Asia Nanjing 2019 ICPC南京站网络赛 B super_log(欧拉降幂)

题目链接:https://nanti.jisuanke.com/t/41299

 

题目大意:

 

定义这么一种运算,求满足的最小正整数x,求x%m的值

 

题目思路:

当事人就是痛苦,非常的痛苦!!!!!!尼玛预处理写错了,太丢人了.........................
还是训练强度太弱,不能再这么颓靡了

 

首先观察这玩意儿,x到0的时候是-1,然后递归回去一层得到0,然后是1,接着是2,然后3.......这样就可以发现,想要让x尽可能小,其实就是a^a^a^a^a...(b个a),实在不放心的小伙伴可以试试,b个a的幂次代进去就是b

然后就是牛B的欧拉降幂

后面两条其实并不需要gcd一定要不为1,只要大小关系符合要求就可以用

所以我的方法是,先预处理出a^a^a^a...中小于1e8的,因为模范围1e6,所以没预处理出来的数一定是大于它模的欧拉函数的,那么也就直接使用最后一条公式,不需要分类讨论,好像跟其他人的写法不太一样,但是我感觉我的更好理解也更不容易错

所以。。。这题我居然错在了,我把底的优先级当成比算幂的优先级高了,结果一直没发现以为是欧拉降幂写错了

知道真相的我眼泪掉下来

 

以下是代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e6 + 5;
#define rep(i,a,b) for(int i=a;i<=b;i++)
typedef double db;
int euler[maxn];
void get(){
    memset(euler,0,sizeof(euler));
    euler[1]=1;
    for(int i=2;i<maxn;i++){
        if(!euler[i]){
            for(int j=i;j<maxn;j+=i){
                if(!euler[j]){
                    euler[j]=j;
                }
                euler[j]=euler[j]/i*(i-1);
            }
        }
    }
}
ll qpow(ll di,ll mi,ll mod)
{
    ll ans = 1;
    while(mi)
    {
        if(mi & 1)
            ans = ans*di % mod;
        di = di*di%mod;
        mi>>=1;
    }
    return ans;
}
int pos;
ll p[maxn];
ll a,b,m;
ll dfs(ll n,ll m){
    if(m==1)return 0;
    if(n<=pos){
        if(p[n]<m)return p[n];
        return p[n]%m+m;
    }
    ll rst=dfs(n-1,euler[m]);
    return qpow(a,euler[m],m)*qpow(a,rst,m)%m;
}
int  main()
{
    get();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&a,&b,&m);
        if(a==1||!b){
            printf("%lld\n",1%m);
            continue;
        }
        pos=0;
        ll temp=a;
        while(pos<b){
            p[++pos]=temp;
            ll temp2=1;
            rep(i,1,temp){
                temp2*=a;
                if(temp2>=1e8)break;
            }
            if(temp2>=1e8)break;
            temp=temp2;
        }
        printf("%lld\n",dfs(b,m)%m);
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值