2021杭電多校1 1007/HDU 6956 Pass!
阿新 • • 發佈:2021-07-22
題目連結:https://acm.hdu.edu.cn/showproblem.php?pid=6956
題目大意:n個人傳球,球最開始在第1個人手裡,接下來每秒拿球的人必須傳給另一個人,記合法方案為最後求傳給第1個人,第i秒的合法方案數為f(i),現在知道了方案數,求最小時間t使得f(t) = x (mod 998244353)
題目思路:通過遞推得出f(i)=(n-2)f(i-1)+(n-1)f(i-2),再通過特徵方程求解數列的通項公式得出 f(t)=((n-1)t+(n-1)*(-1)t) / n = x (mod 998244353) 感謝這篇部落格提供的解法:https://www.cnblogs.com/ZX-GO/p/15039734.html
000AC程式碼:
#include <unordered_map> #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <string> #include <stack> #include <deque> #include <queue> #include <cmath> #include <map> #include <set> using namespace std; typedef pair<int, int> PII; typedef long long ll; typedef unsigned long long ull; const int INF = 0x3f3f3f3f; const int N = 1e5 + 10, M = 1e7 + 30; const int base = 1e9; const int P = 131; const int mod = 998244353; const double eps = 1e-8; const double PI = acos(-1.0); ll hs[N], head[N], nexts[N], id[N], top; void insert(ll x, ll y, ll mod) //mod傳 N { ll k = x % mod; hs[top] = x; id[top] = y; nexts[top] = head[k]; head[k] = top++; } ll find(ll x, ll mod) { ll k = x % mod; for (int i = head[k]; i != -1; i = nexts[i]) if (hs[i] == x) return id[i]; return -1; } ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); } ll BSGS(ll a, ll b, ll p, ll a1) //質數傳1 { memset(head, -1, sizeof(head)); top = 1; a %= p, b %= p; if (a1 == 1 && 1 % p == b % p) return 0; if (a == 0) { if (b == 0) return 1; else return -1; } //unordered_map<ll, ll> hash; //map unordered_map 都試試 ll k = sqrt(p) + 1; ll ak = 1; for (ll i = 0; i < k; ++i) { ll t = ak * b % p; insert(t, i, N); //hash[t] = i; ak = ak * a % p; } for (ll i = 0; i <= k; ++i) { /* if (hash.count(a1) && i * k - hash[a1] >= 0) return i * k - hash[a1]; */ ll j = find(a1, N); if (j != -1 && i * k - j >= 0) return i * k - j; a1 = a1 * ak % p; } return -1; } ll exBSGS(ll a, ll b, ll p) { a %= p, b %= p; if (b == 1 || p == 1) return 0; ll cnt = 0, a1 = 1; ll d = gcd(a, p); while (d > 1) { if (b % d) return -1; p /= d; b /= d; a1 = (a1 * a / d) % p; ++cnt; if (b == a1) return cnt; d = gcd(a, p); } ll res = BSGS(a, b, p, a1); if (res == -1) return -1; else return res + cnt; } int main() { int T; scanf("%d", &T); while (T--) { ll n, x; scanf("%lld%lld", &n, &x); ll ans1 = exBSGS((n - 1), n * x + (n - 1), mod); if (ans1 % 2 == 0 || ans1 == -1) ans1 = INF; ll ans2 = exBSGS((n - 1), n * x + (1 - n), mod); if (ans2 % 2 == 1 || ans2 == -1) ans2 = INF; ll ans = min(ans1, ans2); if (ans == INF) printf("-1\n"); else printf("%lld\n", ans); } return 0; }