EOJ Monthly 2021.9 Sponsored by TuSimple——A.Amazing.Discovery(分治or二次剩余)

Posted H-w-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EOJ Monthly 2021.9 Sponsored by TuSimple——A.Amazing.Discovery(分治or二次剩余)相关的知识,希望对你有一定的参考价值。

EOJ Monthly 2021.9 Sponsored by TuSimple

A.Amazing.Discovery

题意:

给出 a , b , n a,b,n abn,求
S = ( a + b ) n + ( a − b ) n ( m o d   p ) S=(a+\\sqrt b)^n+(a-\\sqrt b)^n(mod~p) S=(a+b )n+(ab )n(mod p)

思路:

因为 b \\sqrt b b 可能在模 m o d mod mod的情况下没有整数解。

解法1:

S n = ( a + b ) n + ( a − b ) n S_n=(a+\\sqrt b)^n+(a-\\sqrt b)^n Sn=(a+b )n+(ab )n

S 2 n = ( a + b ) 2 n + ( a − b ) 2 n = S n 2 − 2 ( a + b ) n ( a − b ) n = S n 2 − 2 ( a 2 − b ) n S_2n=(a+\\sqrt b)^2n+(a-\\sqrt b)^2n=S_n^2-2(a+\\sqrt b)^n(a-\\sqrt b)^n=S_n^2-2(a^2-b)^n S2n=(a+b )2n+(ab )2n=Sn22(a+b )n(ab )n=Sn22(a2b)n

S 2 n + 1 = ( a + b ) 2 n + 1 + ( a − b ) 2 n + 1 = S n S n + 1 − ( a + b ) n ( a − b ) n + 1 − ( a + b ) n + 1 ( a − b ) n = S n 2 − 2 a ( a 2 − b ) n S_2n+1=(a+\\sqrt b)^2n+1+(a-\\sqrt b)^2n+1=S_nS_n+1-(a+\\sqrt b)^n(a-\\sqrt b)^n+1-(a+\\sqrt b)^n+1(a-\\sqrt b)^n=S_n^2-2a(a^2-b)^n S2n+1=(a+b )2n+1+(ab )2n+1=SnSn+1(a+b )n(ab )n+1(a+b )n+1(ab )n=Sn22a(a2b)n

分奇数和偶数往下进行分治(记忆化一下,减少算的次数)

#include <bits/stdc++.h>
#define lson rt << 1
#define rson (rt << 1) | 1

using namespace std;

typedef long long ll;
const int mod = 998244353;
ll qpow(ll x, ll y) 
    ll ans = 1;
    while(y) 
        if(y & 1) ans = ans * x % mod;
        x = x * x % mod;
        y >>= 1;
    
    return ans;

map<ll, ll> mp;
ll solve(ll a, ll b, ll n) 
    if(mp.find(n) != mp.end()) return mp[n];
    else if(n == 1) return mp[1] = 2ll*a;
    else 
        if(n % 2 == 0) 
            ll tmp = solve(a, b, n/2);
            return mp[n] = ((tmp * tmp % mod - 2ll * qpow((a*a%mod-b+mod)%mod, n/2) % mod) % mod + mod) % mod;
        
        else 
            int k = n/2;
            ll tmp1 = solve(a, b, k), tmp2 = solve(a, b, n-k);
            return mp[n] = ((tmp1 * tmp2 % mod - 2ll * a % mod * qpow((a*a%mod-b+mod)%mod, n/2) % mod) % mod + mod) % mod;
        
    


int main() 
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    ll a, b, n;
    cin >> a >> b >> n;
    cout << solve(a, b, n); 



解法2:

二次剩余(简单理解)

用二次剩余 C i p o l l a Cipolla Cipolla算法中的类似复数域的东西可以直接求解。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

以上是关于EOJ Monthly 2021.9 Sponsored by TuSimple——A.Amazing.Discovery(分治or二次剩余)的主要内容,如果未能解决你的问题,请参考以下文章

矩阵快速幂EOJ EOJ Monthly 2021.9 Sponsored by TuSimple A. Amazing Discovery

矩阵快速幂EOJ EOJ Monthly 2021.9 Sponsored by TuSimple A. Amazing Discovery

EOJ Monthly 2021.9 Sponsored by TuSimple——A.Amazing.Discovery(分治or二次剩余)

EOJ Monthly 2019.2

EOJ Monthly 2018.2

[EOJ Monthly] 2019.9