CodeForces 919E Congruence Equation(费马小定理+逆元)

E. Congruence Equation
time limit per test:3 seconds
memory limit per test:256 megabytes
input:standard input
output:standard output

Given an integer x. Your task is to find out how many positive integers n (1 ≤ n ≤ x) satisfy

where a, b, p are all known constants.
Input

The only line contains four integers a, b, p, x (2 ≤ p ≤ 106 + 3, 1 ≤ a, b < p, 1 ≤ x ≤ 1012). It is guaranteed that p is a prime.

Output

Print a single integer: the number of possible answers n.

Examples
Input
2 3 5 8
Output
2
Input
4 6 7 13
Output
1
Input
233 233 10007 1
Output
1
Note

In the first sample, we can see that n = 2 and n = 8 are possible answers.




        好久没有写博客了,之前呢因为考试月还有雅思耽搁了挺久的,今天正式复出。
        这道题,如果是现在拿给我做,应该是可以拿下的,在经历了给大一培训的一段时间之后。这题其实和我找的某一道题目有点类似,都是用费马小定理。
        
        我们可以把 n 表示为 n= i*(p-1)+j。如此一来等式就是 ( i*(p-1)+j)*a^(i*(p-1)+j)≡b(mod p)。根据别的题的经验,利用费马小定理 a^(p-1)≡1(mod p),等式可以化为 (i*(p-1)+j)*a^j≡b(mod p)。 最后,我们就可以继续化简,i=(b*a^(-j) - j) / (p-1) + k*p。显然,我们可以枚举j(0<j<p),然后对于每一个j,看有多少个i,即有多少个k的取值。由于满足 n<x,即 i*(p-1)+j<x,我们可以求出一个 i 的上界,设为up,然后设当k取0的时候 i 的值为first,那么满足的方案数就是 (up-first)/p。统计所有的个数即可。
        具体见代码:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long
#define N 200010

using namespace std;

LL qpow(LL a,LL b,LL mod)
{
    LL ans=1LL;
    while(b)
    {
        if(b&1)ans=(LL)ans*a%mod;
        a=(LL)a*a%mod; b>>=1;
    }
    return ans;
}

LL a,b,p,x;

int main()
{
    LL ans=0;
    cin>>a>>b>>p>>x;
    int invp=qpow(p-1,p-2,p);					//(p-1)的逆元
    for(int i=1;i<p;i++)
    {
        LL c=qpow(qpow(a,p-2,p),i,p)*b%p;
        LL first=((c-i)%p+p)%p*invp%p;				//first
        LL up=(x-i)/(p-1);					//上界
        if (i+first*(p-1)>x) continue;
        ans+=(up-first)/p+1;					//统计结果
    }
    cout<<ans<<endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值