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;
}
posted @ 2019-02-10 19:18  Dream_maker_yk  阅读(...)  评论(... 编辑 收藏