CF919E Congruence Equation

一、题目

点此看题

二、解法

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

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

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

综合这两个条件,我们可以解方程,用不到中国剩余定理,直接构造即可(下面的 b b 表示的是上面的 b × i n v ( a x ) b\times inv(a^x) ):
( p 1 ) × ( x b ) + x (p-1)\times(x-b)+x p , p 1 p,p-1 带进去模就能发现它是满足条件的,设它算出来的值为 t m p tmp ,我们先把 t m p tmp p × ( p 1 ) p\times(p-1) ,得到最小的正整数解,先和 x x 比大小,然后再算贡献即可,时间复杂度 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)
*/
发布了257 篇原创文章 · 获赞 13 · 访问量 6717

猜你喜欢

转载自blog.csdn.net/C202044zxy/article/details/104206460
今日推荐