codeforces 919E. Congruence Equation

/*
题意:n*a^n≡b(mod p),其中1<=n<=x,求满足条件的n的个数
思路:令n=i×(p−1)+j,因为根据费马小定理可以保证j有解,所以有
				n*a^(i*(p-1)+j)≡b(mod p)
				n≡b*a^-1(mod p)
				i×(p−1)+j≡b*a^-1(mod p)
				j-i≡b*a^-1(mod p)
	我们枚举j,此时j介于1与p-1之间,令c=b*a^-1(mod p),
	求出i,之后求出最小的n满足条件,注意到循环节为p*(p-1)
	所以n+k*p(p-1)就是此时j固定的解,用x去除便可得出数量
	(此时加上循环节不会影响答案,只是为了充分利用x的大小而已)
	特判n=0,此时不满足题意,我们只去考虑循环节就行
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;

ll qpow(ll a, ll b, ll p)
{
	ll ans = 1;
	while (b)
	{
		if (b & 1)
			ans = ans*a%p;
		a = a*a%p;
		b /= 2;
	}
	return ans;
}

int main()
{
	ll a, b, x, p;
	scanf("%lld%lld%lld%lld", &a, &b, &p, &x);

	ll ans = 0, repetend = p*(p - 1);
	for (ll j = 1; j <= p - 1; j++)
	{
		ll c = b*qpow(qpow(a, j, p), p - 2, p) % p;//b*逆元
		ll i = (j - c + p) % p;
		ll n = (i*(p - 1) + j) % repetend;
		if (n == 0)//特判n>0
			n = repetend;
		ans += x / repetend + (x%repetend >= n);
	}
	printf("%lld\n", ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Egqawkq/article/details/79312584
今日推荐