欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

2019牛客暑期多校训练营(第五场)C generator 2 (BSGS)

发布时间:2023/12/4 编程问答 54 豆豆
生活随笔 收集整理的这篇文章主要介绍了 2019牛客暑期多校训练营(第五场)C generator 2 (BSGS) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

2019牛客暑期多校训练营(第五场)C generator 2

思路

x0=x0x_0 = x_0x0=x0

x1=a∗x0∗bx_1 = a * x_0 * bx1=ax0b

x2=a∗x1+b=a2∗x0+a∗b+bx_2 = a * x_1 + b = a ^{2} * x_0 + a * b + bx2=ax1+b=a2x0+ab+b

容易发现后项是一个等比数列求和

xn=anx0+b(1−an)1−ax_n = a ^ {n} x_0 + \frac {b (1 - a ^ n)} {1 - a}xn=anx0+1ab(1an)

我们要求xn=vx_n = vxn=v,化简

anx0+b(1−an)1−a=va ^ {n} x_0 + \frac {b (1 - a ^ n)} {1 - a} = vanx0+1ab(1an)=v

anx0(1−a)+b(1−an)=v(1−a)a ^{n} x_0(1 - a) + b (1 - a ^ n) = v(1 - a)anx0(1a)+b(1an)=v(1a)

an(x0−ax0−b)=v(1−a)−ba ^ n (x_0 - ax_0 - b) = v(1 - a) - ban(x0ax0b)=v(1a)b

an=v(1−a)−bx0−ax0−ba^n =\frac {v (1 - a) - b} {x_0 - a x_0 - b}an=x0ax0bv(1a)b

上面式子都是modp\mod pmodp下的同余等式,为了方便写了===

看到这里就简单了,我们要求解的是nnn,显然右边这一坨都是已知的,我们假定为BBB,求解an=Ba ^ n = Ban=B,这不就是个裸题了吗。

这道题目还要稍加分类讨论一下:

  • a == 0

x0=x0,xi=b(i>=1)x_0 = x_0, x_i = b(i >= 1)x0=x0,xi=b(i>=1)

  • a==1a == 1a==1

因为这种情况上面不能直接相除,所以我们需要特殊考虑ai=b+i∗aa_i = b + i * aai=b+ia

也就是求解i∗a=v−bi * a = v - bia=vb,这个时候只要左右两边同时乘以aaa的逆元即可得到我们要的iii

代码

/*Author : lifehappy */ #pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc++.h> #define mp make_pair #define pb push_back #define endl '\n'using namespace std;typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii;const double pi = acos(-1.0); const double eps = 1e-7; const int inf = 0x3f3f3f3f;inline ll read() {ll f = 1, x = 0;char c = getchar();while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9') {x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return f * x; }void print(ll x) {if(x < 10) {putchar(x + 48);return ;}print(x / 10);putchar(x % 10 + 48); }ll quick_pow(ll a, ll n, ll mod) {ll ans = 1;while(n) {if(n & 1) ans = (ans * a) % mod;a = (a * a) % mod;n >>= 1;}return ans; }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int T = read();while(T--) {ll n = read(), x0 = read(), a = read(), b = read(), p = read();ll x = 1, Unit = quick_pow(a, 1000, p);unordered_map<ll, int> MP;for(int i = 1; i <= 1000000; i++) {x = (x * Unit) % p;if(!MP.count(x)) {MP[x] = i * 1000;}}ll inv = quick_pow(((x0 - a * x0 - b) % p + p) % p, p - 2, p);int t = read();while(t--) {ll v = read();if(a == 0) {if(v % p == x0 % p) {puts("0");}else if(v % p == b % p) {puts("1");}else {puts("-1");}continue;}if(a == 1) {ll ans = (((((v - x0) % p + p) % p) * quick_pow(b, p - 2, p))) % p;if(ans < n) {printf("%lld\n", ans);}else {puts("-1");}continue;}v = (((v * (1 - a) - b) % p + p) % p * inv) % p;if(Unit == 0) {if(v == 0) {puts("0");}else {puts("-1");}continue;}x = v;int ans = p + 1;for(int i = 0; i <= 1000; i++) {if(MP.count(x)) {ans = min(ans, MP[x] - i);}x = (x * a) % p;}if(ans != p + 1 && ans < n) {printf("%d\n", ans);}else {puts("-1");}}}return 0; }

总结

以上是生活随笔为你收集整理的2019牛客暑期多校训练营(第五场)C generator 2 (BSGS)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。