[数论][二次剩余][BSGS] CodeChef FN
2017-09-05 20:02
435 查看
Description
设Fn是斐波那契数列第n项,给定FnmodP和P求最小的n。保证5在膜P意义下有二次剩余。
Solution
经过一系列xjb推会发现FnmodP是循环的。所以答案小于P。首先用Cipolla算法求出5的二次剩余。
考虑Fn的通项公式。设x=5√,y=5√+12就有Fn=1x[yn+(−y)−n]通过解一元二次方程,可以得到yn之后就BSGS求一下n,求的时候判下奇偶性就好啦。
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll A, C, P, Ans, test, Yn, Y; map<ll, ll> ap; ll w, rtf, RT, res; struct Complex { ll r, i; Complex(ll _r = 0, ll _i = 0):r(_r), i(_i) {} inline Complex operator +(ll x) { return Complex((x + r) % P, i); } inline Complex operator *(Complex a) { ll rr = (a.r * r % P + w * a.i % P * i % P + P * 3) % P, ii = (a.i * r % P + a.r * i % P) % P; return Complex(rr, ii); } }; inline ll Pow(Complex a, ll b) { Complex c = 1; while (b) { if (b & 1) c = c * a; a = a * a; b >>= 1; } return c.r; } inline ll Pow(ll a, ll b) { ll c = 1; while (b) { if (b & 1) c = c * a % P; a = a * a % P; b >>= 1; } return (c + P) % P; } inline ll Inv(ll a, ll P) { return Pow(a, P - 2); } ll Log(ll a, ll b, ll p, ll par) { ap.clear(); ll m = ceil(sqrt(p)), ia = Inv(Pow(a, m), P), res; res = Inv(b, p); par ^= 1; for (int i = 0; i < m; i++) { if (!ap.count(res)) ap[res] = i; res = res * a % P; } res = 1; for (int i = 0; i <= m; i++) { if (ap.count(res) && (((ap[res] + i * m) & 1) ^ par)) return ap[res] + i * m; res = res * ia % P; } return -1; } inline ll Qr(ll x, ll p) { if (Pow(x, (P - 1) / 2) == P - 1) return -1; if (Pow(x, (P - 1) / 2) == 0) return 0; ll a; Complex k(0, 1); while (true) { a = rand(); if (Pow((a * a - x + P) % P, (P - 1) / 2) == P - 1) break; } w = (a * a - x + P) % P; return Pow(k + a, (P + 1) / 2); } inline ll Min(ll a, ll b) { return a < b ? a : b; } int main(void) { freopen("1.in", "r", stdin); freopen("1.out", "w", stdout); scanf("%d", &test); srand(19260817); while (test--) { scanf("%lld%lld", &C, &P); rtf = Qr(5, P); Ans = P; A = C * rtf % P; Y = (rtf + 1) * (P + 1) / 2 % P; RT = Qr((A * A % P + 4) % P, P); if (~RT) { Yn = (A + RT) * (P + 1) / 2 % P; res = Log(Y, Yn, P, 0); if (~res) Ans = Min(Ans, res); Yn = (A - RT + P) * (P + 1) / 2 % P; res = Log(Y, Yn, P, 0); if (~res) Ans = Min(Ans, res); } RT = Qr((A * A % P - 4 + P) % P, P); if (~RT) { Yn = (A + RT) * (P + 1) / 2 % P; res = Log(Y, Yn, P, 1); if (~res) Ans = Min(Ans, res); Yn = (A - RT + P) * (P + 1) / 2 % P; res = Log(Y, Yn, P, 1); if (~res) Ans = Min(Ans, res); } if (Ans == P) Ans = -1; printf("%lld\n", Ans); } }
相关文章推荐
- [数论 && 二次剩余 && BSGS] Codechef FN. FIBNACCI NUMBER
- [斐波那契数列 求解二次剩余&二次模方程 BSGS] COGS 2114 [CodeChef FN]斐波那契数
- BSGS与二次剩余
- 【数论】【二次剩余】【map】hdu6128 Inverse of sum
- URAL 1132 Square Root <二次剩余 + 数论>
- CodeChef:Fombinatorial(数论 & 逆元)
- bzoj 5104: Fib数列 二次剩余+BSGS
- 基本数论(从整除入门到欧拉弃坑到中国剩余BSGS跑路)
- [zoj 3774]Power of Fibonacci 数论(二次剩余 拓展欧几里得 等比数列求和)
- HDU 4794 Arnold ACM/ICPC 2013 Changsha(二次剩余+数论)
- hdu3589 Jacobi symbol(二次剩余 数论题)
- CodeChef:Devasena(数论)
- [求解二次剩余 数论技巧 随机化] Ural 1132 Square Root
- hdu3589 Jacobi symbol(二次剩余 数论题)
- [zoj 3774]Power of Fibonacci 数论(二次剩余 拓展欧几里得 等比数列求和)
- ECC与数论、数论史、代数,二次剩余符号的程序计算,高次剩余,高斯和 2013-03-23 21:52:49
- [ 杜教筛 数论 ] Codechef January Challenge 2018 #SQRGOOD
- bzoj2219: 数论之神【中国剩余定理+原根+BSGS】
- codeforces#232_div2_C On Number of Decompositions into Multipliers 数论 组合计数
- uva11754 - Code Feat 枚举 中国剩余定理