当时以一看见这题,n的范围这么大,脑子里全是欧拉降幂。(感觉要是有人跟我说这不是欧拉降幂,我就跟他急似的);然后就瞎搞了很久,然后。。。。。就没有然后了。比赛结束后看了一下题解
出这题是因为我小时候曾被Codeforces 某个不是用2 进制倍增,而是改用10 进制倍增就会
很好写的题震慑到,所以这次找了个纯用2 进制倍增有点困难的题和大家分享
这是大佬题解的结束语,我哭了,小时候,和我小时玩的cf完全不是一个东西嘛;
思路:
仿造我们写快速幂的写法,写快速幂的时候我们把指数按二进制分解了。其实只是方便而已。其实只有你高兴,随便你按几进制分解都可以。那么本题就是按照十进制分解的;哎,涨知识了。
假设A是我们构造的矩阵,那么我们要求的就是A^n,(n是很大的数),最后的结果记为ans,ans初始为单位矩阵。那么让我们先处理出A的1次方~到A的九次方。比如我们n=12345465(字符表示的),那么我们从左到右处理,先是1,那么就是ans的10次方*A[1],之后是2,那么就是ans的10次方 * A[2],为什么这里是乘A,而不是加呢。记住n是这指数上,分开后就是乘法了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1000 * 1000 + 10;
ll n, m, mod;
ll x0, x1, a, b;
char s[maxn];
inline ll ksc(ll x, ll y, ll p) {
ll z = (long double)x / p * y;
ll res = (unsigned ll)x*y - (unsigned ll)z*p;
return (res + p) % p;
}
struct Mat {
ll a[3][3];
Mat() {
memset(a, 0, sizeof(a));
}
Mat operator*(Mat A) {
Mat ans;
for (int i = 1; i <= 2; i++) {
for (int j = 1; j <= 2; j++) {
for (int k = 1; k <= 2; k++) {
ans.a[i][j] = (ans.a[i][j] + a[i][k] * A.a[k][j]) % mod;
}
}
}
return ans;
}
Mat operator^(int n) {
Mat ans; ans.a[1][1] = ans.a[2][2] = 1;
Mat a = *this;
while (n) {
if (n & 1)ans = ans * a;
n >>= 1;
a = a * a;
}
return ans;
}
}Ma, Mb, M[10], ans;
void init() {
M[0].a[1][1] = M[0].a[2][2] = 1;
for (int i = 1; i < 10; i++)M[i] = M[i - 1] * Ma;
}
int main() {
scanf("%lld%lld%lld%lld", &x0, &x1, &a, &b);
scanf("%s", s);
scanf("%lld", &mod);
Ma.a[1][1] = a, Ma.a[1][2] = 1; Ma.a[2][1] = b, Ma.a[2][2] = 0;
Mb.a[1][1] = x1, Mb.a[1][2] = x0;
ans.a[1][1] = ans.a[2][2] = 1;
init();
ll n = 0, len = strlen(s);
if (n == 1) {
printf("%lld\n", x0);
return 0;
}
for (ll i = 0; i < len; i++) {
ans = ans^10;
ans = ans * M[s[i] - '0'];
}
printf("%lld\n", (Mb*ans).a[1][2]);
return 0;
}