Official
E - Geometric Progression Editorial
by
E - Geometric Progression Editorial
by
cn449
数列 を で定めると、、 を満たします。求めるべきものは です。
ここで、上の漸化式より行列を用いて と表すことができます。
であったため、 です。
の各成分を で割った余りは繰り返し二乗法を用いて で求めることができます(整数の 乗を で割った余りを求めるのと同様の要領です)。
よってこの問題を で解くことができました。
なお、 ですが、これを利用して解こうとする場合 における の逆元が存在するとは限らないことに注意してください。
実装例
Copy
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;
vector<vector<ll>> mat_mul(vector<vector<ll>> a, vector<vector<ll>> b, ll mod) {
// 行列乗算
int n = a.size();
vector<vector<ll>> res(n, vector<ll>(n));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
res[i][j] += a[i][k] * b[k][j];
res[i][j] %= mod;
}
}
}
return res;
}
vector<vector<ll>> mat_pow(vector<vector<ll>> a, ll b, ll mod) {
// 行列累乗
int n = a.size();
vector<vector<ll>> res(n, vector<ll>(n));
for (int i = 0; i < n; i++) res[i][i] = 1;
while (b) {
if (b & 1) res = mat_mul(res, a, mod);
a = mat_mul(a, a, mod);
b >>= 1;
}
return res;
}
int main() {
ll a, x, m;
cin >> a >> x >> m;
vector<vector<ll>> f = { {a,1},{0,1} };
vector<vector<ll>> g = mat_pow(f, x, m);
cout << g[0][1] << '\n';
}
#include <iostream> #include <vector> using namespace std; using ll = long long; vector<vector<ll>> mat_mul(vector<vector<ll>> a, vector<vector<ll>> b, ll mod) { // 行列乗算 int n = a.size(); vector<vector<ll>> res(n, vector<ll>(n)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < n; k++) { res[i][j] += a[i][k] * b[k][j]; res[i][j] %= mod; } } } return res; } vector<vector<ll>> mat_pow(vector<vector<ll>> a, ll b, ll mod) { // 行列累乗 int n = a.size(); vector<vector<ll>> res(n, vector<ll>(n)); for (int i = 0; i < n; i++) res[i][i] = 1; while (b) { if (b & 1) res = mat_mul(res, a, mod); a = mat_mul(a, a, mod); b >>= 1; } return res; } int main() { ll a, x, m; cin >> a >> x >> m; vector<vector<ll>> f = { {a,1},{0,1} }; vector<vector<ll>> g = mat_pow(f, x, m); cout << g[0][1] << '\n'; }
posted:
last update: