【厦门大学“网宿杯“17届程序设计竞赛决赛】D-财富密码
财富密码
https://ac.nowcoder.com/acm/contest/5945/D
题意:
给定 ,其中 。
求有多个 ,满足 。
题解:
需要一些简单的数论知识:
费马小定理:若 为质数,而整数 不是 的倍数,则 。
逆元:定义整数 在模 意义下的逆元为 ,则 ,可记作 。
在 条件下,有 。因为 。
然后到这道题:
首先由 费马小定理 可以得到 ,
因此可以设 。
然后推式子:
由于 ,范围为 。故可以枚举 ,通过上式计算 。
需要用到快速幂,一次计算的复杂度在 级别。整体估计复杂度是可以通过的。
在已知 的情况下,我们根据这个式子可以求出一个 ,
显然任意 ,
即 ,
都有: 时 。
有限制条件: 。
对于一个确定的 ,我们要求的就是有多少个整数 ,使得 在范围之内。
然后在范围内的计入答案就可以了。
Code:
#include <bits/stdc++.h> using namespace std; using ll = long long; int a, b, p; ll x; int qpow(int x, int n) { assert(n >= 0); int res = 1; while(n) { if(n & 1) res = 1ll * res * x % p; x = 1ll * x * x % p; n >>= 1; } return res; } int inv(int x) { return qpow(x, p - 2); } int main() { cin >> a >> b >> p >> x; ll ans = 0; int inv1 = inv(p - 1); for(int t = 0; t < p - 1; t++) { int k = (1ll * b * inv(qpow(a, t)) - t) * inv1 % p; k = (k + p) % p; ll d = x - 1ll * k * (p - 1) - t; if(d >= 0) ans += d / (1ll * p * (p - 1)) + 1; } cout << ans << endl; }