题目:
思路:
n
∗
a
n
=
b
(
m
o
d
p
)
n*a^n=b\ (mod\ p)
n∗an=b (mod p)
令
n
=
i
+
(
p
−
1
)
∗
k
(
m
o
d
p
)
n=i+(p-1)*k\ (mod\ p)
n=i+(p−1)∗k (mod p)
得到
k
=
(
b
/
a
i
−
i
)
/
(
p
−
1
)
(
m
o
d
p
)
/
/
k=(b/a^i-i)/(p-1)\ (mod\ p) //
k=(b/ai−i)/(p−1) (mod p)//费马小定理
然后枚举
i
∈
[
0
,
p
−
2
]
i∈[0,p-2]
i∈[0,p−2],对于每一个
i
i
i 可以得到最小的正整数
k
k
k 满足同余式,那么
k
+
p
∗
j
k+p*j
k+p∗j 都是满足同余的,此时只需要保证
i
+
(
p
−
1
)
∗
(
k
+
p
∗
j
)
<
=
x
i+(p-1)*(k+p*j)<=x
i+(p−1)∗(k+p∗j)<=x 即
n
<
=
x
n<=x
n<=x 即可完美的不重不漏统计答案。
同余还是秒啊啊
/* Author : Rshs */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
LL infa[MXN],inv[MXN],fac[MXN];
void CCinit(int n,LL p){
fac[0]=1;
infa[1]=inv[1]=fac[1]=1;
for(LL i=2;i<=n;i++) fac[i]=fac[i-1]*i%p; //阶乘
for(LL i=2;i<=n;i++) inv[i]=(p-p/i)*inv[p%i]%p; //逆元
for(LL i=2;i<=n;i++) infa[i]=infa[i-1]*inv[i]%p; //逆元前缀乘
}
int main(){
LL a,b,p,x;cin>>a>>b>>p>>x;
CCinit(1e6+5,p);
LL ans=0;
LL ai=1;
for(LL i=0;i<p-1;i++,ai=ai*a%p){
LL k=(b*inv[ai]%p-i)*inv[p-1]%p;
k=(k+p)%p; //最小的k,之后k不停+p,要保证n=+k*(p-1)<=x
LL yu=x-k*(p-1)-i;
if(yu<0)continue;
ans++;
ans+=(yu/(p*(p-1)));
}
cout<<ans<<'\n';
return 0;
}