A. Amazing Discovery
这题主要是要跳出组合数学的思维去考虑其他的可行办法,我们可以考虑用分治去写。
首先设 S n = ( a + b ) n + ( a − b ) n S_n=(a+\sqrt{b})^n+(a-\sqrt{b})^n Sn=(a+b)n+(a−b)n
①若
n
n
n 为偶数,则有:
(
S
n
2
)
2
=
S
n
+
2
×
(
a
2
−
b
)
n
2
(S_{\frac{n}{2}})^2 = S_n+2×(a^2-b)^{\frac{n}{2}}
(S2n)2=Sn+2×(a2−b)2n
②若
n
n
n 为奇数,设
x
=
⌊
n
2
⌋
x=\lfloor\frac{n}{2}\rfloor
x=⌊2n⌋ ,
y
=
n
−
x
y=n-x
y=n−x
S
x
×
S
y
=
S
n
+
2
×
a
×
(
a
2
−
b
)
x
S_x ×S_y=S_n+2×a×(a^2-b)^x
Sx×Sy=Sn+2×a×(a2−b)x
且我们可以得知 S 1 = 2 a S_1=2a S1=2a ,于是我们就可以分治加记忆化去求解答案。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
ll a, b, n;
map<int, ll> mp;
ll ksm(ll base, ll n) {
base = (base % mod + mod) % mod;
ll ans = 1;
while(n) {
if (n & 1) ans = ans * base % mod;
base = base * base % mod;
n >>= 1ll;
}
return ans;
}
ll cal(ll n) {
if (n == 1) return 2 * a;
if (mp.find(n) != mp.end()) return mp[n];
if (n & 1) {
int num1 = n / 2;
int num2 = n - n / 2;
return mp[n] = (cal(num1) * cal(num2) % mod - 2 * a % mod * ksm(a * a - b, num1) % mod + mod) % mod;
}
ll tmp = cal(n / 2);
return mp[n] = (tmp * tmp % mod - 2 * ksm(a * a - b, n / 2) % mod + mod) % mod;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
scanf("%lld%lld%lld", &a, &b, &n);
printf("%lld\n", cal(n));
}