题意:有n个人,当前有一个球在第一个人手中,每一个时间持球人都会将球扔给其他人,在t时间后球在第一个人手中,现在告诉你整个过程中扔球方案数在对998244353取模后为x,问最小的t为多少
解法:
①记dp[i][0]为t=i时球不在第一人人手中的方案数,dp[i][1]为t=i时球在第一个人手中,易知
d
p
[
i
]
[
0
]
=
d
p
[
i
−
1
]
[
1
]
∗
(
n
−
1
)
+
d
p
[
i
−
1
]
[
0
]
∗
(
n
−
2
)
dp[i][0]=dp[i-1][1]*(n-1)+dp[i-1][0]*(n-2)
dp[i][0]=dp[i−1][1]∗(n−1)+dp[i−1][0]∗(n−2),
d
p
[
i
]
[
1
]
=
d
p
[
i
−
1
]
[
0
]
dp[i][1]=dp[i-1][0]
dp[i][1]=dp[i−1][0],则有
d
p
[
i
]
[
0
]
=
d
p
[
i
−
2
]
[
0
]
∗
(
n
−
2
)
+
d
p
[
i
−
1
]
[
0
]
∗
(
n
−
1
)
dp[i][0]=dp[i-2][0]*(n-2)+dp[i-1][0]*(n-1)
dp[i][0]=dp[i−2][0]∗(n−2)+dp[i−1][0]∗(n−1)
②通过特征方程与特征根可推导出
d
p
[
i
]
[
1
]
=
d
p
[
i
−
1
]
[
0
]
=
dp[i][1]=dp[i-1][0]=
dp[i][1]=dp[i−1][0]=
(
n
−
1
)
i
−
1
(n-1)^{i-1}
(n−1)i−1
+
(
−
1
)
i
−
1
+(-1)^{i-1}
+(−1)i−1
∗
(
n
−
1
)
=
n
∗
x
*(n-1)=n*x
∗(n−1)=n∗x
m
o
d
mod
mod
p
p
p,个人理解
i
i
i应该为
t
t
t的解,但题目答案却是
i
−
1
i-1
i−1,让我有点不能理解,如果有明白的兄弟可以评论或私信我。(后续:在通过特征方程与特征根推导通项时是以i=1为首项的,即次数的
i
i
i少加了1)
③bsgs:用于解决
a
x
a^{x}
ax=
b
b
b
m
o
d
mod
mod
p
p
p,用一map存取
a
1
a^{1}
a1到
a
(
p
)
a^{\sqrt(p)}
a(p)的值,如果在这个过程中有
a
x
a^{x}
ax
=
b
=b
=b
m
o
d
mod
mod
p
p
p则求出了
x
x
x,如果没有的话,我们搜索
a
i
+
(
p
)
a^{i+\sqrt(p)}
ai+(p)时可以把式子转化为
a
i
a^{i}
ai
=
b
∗
=b*
=b∗
a
−
(
p
)
a^{-\sqrt(p)}
a−(p),即我们只要搜索
b
∗
b*
b∗
a
−
k
(
p
)
a^{-k\sqrt(p)}
a−k(p)是否储存在map中,如果存在,则
x
=
k
∗
p
+
m
p
[
x=k*\sqrt{p}+mp[
x=k∗p+mp[b*
a
−
k
(
p
)
]
a^{-k\sqrt(p)}]
a−k(p)],如果直到
k
∗
p
>
p
k*\sqrt{p}>p
k∗p>p都不满存在上述情况,则
x
x
x不存在
④有推导式发现奇偶会影响b的取值,所以还需要一下情况
AcCode:
#include<iostream>
#include<algorithm>
#include<map>
#include<thread>
#include<unordered_map>
#define int long long
#define inf 100000000000
using namespace std;
int mod = 998244353, maxup;
unordered_map<int, int>mp;
inline int quick_pow(int a, int b) {
int ans = 1;
a %= mod;
while (b) {
if (b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
//inline void vis() {
// for (int i = 5; i > 0; --i)
// {
// std::cout << "error" << std::endl;
// std::this_thread::sleep_for(std::chrono::seconds(1));
// }
//}
signed main() {
int t; scanf("%lld", &t);
maxup = sqrt(mod);
while (t--) {
mp.clear();
int n, x; scanf("%lld %lld", &n, &x);
int a = n - 1;
int b1 = ((n * x + (n - 1)+mod)%mod) * quick_pow(n - 1, mod - 2) % mod;//a=b1
int b2 = ((n * x - (n - 1)+mod) % mod);//a^0表示a^1
if (b1 == 1ll) {
printf("1\n");
continue;
}
if (b2 == 1ll) {
printf("0\n");
continue;
}
int pw = a * a % mod;
int ans = -1, mul = 1;
mp[1] = 0;
for (int i = 1; i <= maxup; i++) {
mul = mul * pw % mod;
if (b2 == mul) {
ans = 2 * i;
break;
}
if (b1 == mul) {
ans = 2 * i + 1;
break;
}
mp[mul] = i;
}
if (ans != -1) {
printf("%lld\n", ans);
continue;
}
int invf = quick_pow(mul, mod - 2);
for (int i = 1; i * maxup < mod; i++) {
b1 = b1 * invf % mod;
b2 = b2 * invf % mod;
if (mp.count(b2)) {
int tans = 2 * i * maxup + 2 * mp[b2];
ans = tans;
break;
}
if (mp.count(b1)) {
int tans = 2 * i * maxup + 2 * mp[b1] + 1;
ans = tans;
break;
}
}
printf("%lld\n", ans);
}
}