题意:给你一个递推式,让你求出第n项
思路:很明显的矩阵快速幂,但是我们该选择怎么加速矩阵快速幂呢,我们采用10进制进行快速幂,就相当与每次缩小了运算的范围。(这道题卡的很紧,我在场上本来是倒着来的,这样就没有办法预处理出每位的快速幂,导致t到哭),没想到题解就是正向的来,预处理出每位即可。
附上代码:
#include<cstdio>
#include<string>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int Max = 2;
long long n = 2;
long long mod;
long long len;
struct Matrix
{
ll a[Max][Max];
Matrix operator * (Matrix b)
{
Matrix c;
memset(c.a, 0, sizeof(c.a));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
for (int k = 0; k < n; k++)
{
c.a[i][j] += (a[i][k] * b.a[k][j]) % mod;
c.a[i][j] %= mod;
}
}
}
return c;
}
}cc;
Matrix fastm(Matrix aa, ll nn)
{
Matrix res;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
res.a[i][j] = 0;
}
for (int i = 0; i < n; i++)
res.a[i][i] = 1;
while (nn)
{
if (nn & 1)
{
res = res * aa;
}
nn >>= 1;
aa = aa * aa;
}
return res;
}
char nx[1000100];
int main(void) {
long long x0, x1, a, b;
scanf("%lld%lld%lld%lld", &x0, &x1, &a, &b);
getchar();
scanf("%s%lld", nx, &mod);
len = strlen(nx);
if (nx[0] == '1'&&len == 1) {
printf("%lld\n", x1);
return 0;
}
Matrix mm;
mm.a[0][0] = x1;
mm.a[0][1] = x0;
mm.a[1][0] = 0;
mm.a[1][1] = 0;
cc.a[0][0] = a;
cc.a[0][1] = 1;
cc.a[1][0] = b;
cc.a[1][1] = 0;
Matrix gg;
gg.a[0][0] = 1;
gg.a[1][1] = 1;
gg.a[0][1] = 0;
gg.a[1][0] = 0;
for(int i=0;i<len;i++){
mm = mm * fastm(cc, nx[len - 1] - '0');
cc = fastm(cc, 10);
}
printf("%lld\n", mm.a[0][1]);
}