1. 程式人生 > 其它 >2021杭電多校1 1007/HDU 6956 Pass!

2021杭電多校1 1007/HDU 6956 Pass!

題目連結: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;
}