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
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;
}