CF919E Congruence Equation

一、题目

点此看题

二、解法

发现 p p p很小,考虑和 p p p有关的算法。

首先想到的肯定是费马小定理吧,我们可以枚举 a x a^x ax的周期 [ 1 , p − 1 ] [1,p-1] [1,p1],设前面的系数为 n n n,那么 n n n是可以被算出来的: n = b × i n v ( a x ) m o d    p n=b\times inv(a^x)\mod p n=b×inv(ax)modp

然后 n n n还有一个限制: n = x m o d    p − 1 n=x\mod p-1 n=xmodp1

综合这两个条件,我们可以解方程,用不到中国剩余定理,直接构造即可(下面的 b b b表示的是上面的 b × i n v ( a x ) b\times inv(a^x) b×inv(ax)):
( p − 1 ) × ( x − b ) + x (p-1)\times(x-b)+x (p1)×(xb)+x p , p − 1 p,p-1 p,p1带进去模就能发现它是满足条件的,设它算出来的值为 t m p tmp tmp,我们先把 t m p tmp tmp p × ( p − 1 ) p\times(p-1) p×(p1),得到最小的正整数解,先和 x x x比大小,然后再算贡献即可,时间复杂度 O ( n ) O(n) O(n)

#include <cstdio>
#define int long long
int read()
{
 int x=0,flag=1;char c;
 while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
 while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
 return x*flag;
}
int a,b,c,p,x,ans;
int qkpow(int a,int b)
{
    int res=1;
    while(b>0)
    {
        if(b&1) res=res*a%p;
        a=a*a%p;
        b>>=1;
    }
    return res;
}
signed main()
{
    a=read();b=read();p=read();x=read();
    a=qkpow(a,p-2);c=p*(p-1);
    for(int i=1;i<p;i++)
    {
        b=b*a%p;
        int tmp=(p-1)*(i-b)+i;
        tmp=(tmp%c+c)%c;
        if(tmp<=x)
            ans+=(x-tmp)/c+1;
    }
    printf("%lld\n",ans);
}
/*
a^x (1<=x<p)
n=b (mod p)
n=i (mod p-1)
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值