zoukankan      html  css  js  c++  java
  • Codeforces1106F 【BSGS】【矩阵快速幂】【exgcd】

    首先矩阵快速幂可以算出来第k项的指数,然后可以利用原根的性质,用bsgs和exgcd把答案解出来


    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    
    const ll N = 1e2 + 10;
    const ll Mod = 998244353;
    
    ll add(ll a, ll b, ll mod = Mod) {
      return (a += b) >= mod ? a - mod : a;
    }
    
    ll sub(ll a, ll b, ll mod = Mod) {
      return (a -= b) < 0 ? a + mod : a;
    }
    
    ll mul(ll a, ll b, ll mod = Mod) {
      return 1ll * a * b % mod;
    }
    
    ll fast_pow(ll a, ll b, ll mod = Mod) {
      ll res = 1;
      for (; b; b >>= 1, a = mul(a, a, mod))
        if (b & 1) res = mul(res, a, mod);
      return res;
    }
    
    ll n, m, k, b[N];
    
    struct Matrix {
      ll g[N][N];
    
      Matrix() {
        memset(g, 0, sizeof(g));
      }
    };
    
    Matrix operator * (const Matrix a, const Matrix b) {
      Matrix c;
      for (ll i = 1; i <= k; i++) 
        for (ll j = 1; j <= k; j++) 
          for (ll p = 1; p <= k; p++) 
            c.g[i][j] = add(c.g[i][j], mul(a.g[i][p], b.g[p][j], Mod - 1), Mod - 1);
      return c;
    }
    
    Matrix fast_pow(Matrix a, ll b) {
      Matrix res;
      for (ll i = 1; i <= k; i++)
        res.g[i][i] = 1;
      for (; b; b >>= 1, a = a * a)
        if (b & 1) res = res * a;
      return res;
    }
    
    ll bsgs(ll a, ll b) {
      map<ll, ll> mp;
      mp[b] = 0;
      ll cur = 1, limit = sqrt(Mod);
      for (ll i = 1; i <= limit; i++) {
        cur = mul(cur, a);
        mp[mul(b, fast_pow(cur, Mod - 2))] = i;
      }
      ll now = 1;
      for (ll i = 0; i <= limit; i++) {
        if (mp.count(now))
          return limit * i + mp[now];
        now = mul(now, cur);
      }
      return -1;
    }
    
    ll gcd(ll a, ll b) {
      return b ? gcd(b, a % b) : a;
    }
    
    void exgcd(ll a, ll b, ll &x, ll &y) {
      if (!b) {
        x = 1, y = 0;
        return;
      }
      exgcd(b, a % b, y, x);
      y -= a / b * x;
    }
    
    ll exgcd(ll a, ll b, ll c) {
      ll g = gcd(a, b);
      if (c % g) return -1;
      ll x, y;
      exgcd(a, b, x, y);
      x *= c / g;
      x = (x % (b / g) + (b / g)) % (b / g);
      return x;
    }
    
    int main() {
    #ifdef dream_maker
      freopen("input.txt", "r", stdin);
    #endif
      scanf("%lld", &k);
      for (ll i = 1; i <= k; i++)
        scanf("%lld", &b[i]);
      scanf("%lld %lld", &n, &m);
      Matrix tmp;
      for (ll i = 1; i < k; i++)
        tmp.g[i][i + 1] = 1;
      for (ll i = 1; i <= k; i++)
        tmp.g[k][i] = b[k - i + 1];
      tmp = fast_pow(tmp, n - k);
      ll ans1 = bsgs(3, m), ans2 = exgcd(tmp.g[k][k], Mod - 1, ans1);
      if (ans1 == -1 || ans2 == -1)
        printf("-1");
      else
        printf("%lld", fast_pow(3, ans2));
      return 0;
    }
    
    
  • 相关阅读:
    LinkedList的实现源码分析
    ArrayList实现源码分析
    探索HashMap实现原理及其在jdk8数据结构的改进
    Maven的安装使用以及 Maven+Spring hello world example
    RedisHelper帮助类
    Stream 和 byte[] 之间的转换
    WCF For Silverlight跨域策略
    Linq Query常见错误
    Linq to Sharepoint--如何获取Linq Query 生成的CALM
    如何使用代码备份SQL Server数据库
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/10360019.html
Copyright © 2011-2022 走看看