EOJ Monthly 2021.9 Sponsored by TuSimple A. Amazing Discovery(分治+记忆化)

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+(ab )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×(a2b)2n

②若 n n n 为奇数,设 x = ⌊ n 2 ⌋ x=\lfloor\frac{n}{2}\rfloor x=2n y = n − x y=n-x y=nx
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×(a2b)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));
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值