题意:
题面写得很清楚。
做法:
首先想到矩阵快速幂。
发现n和m很大,log2承受不了。我们可以转化成10进制来做,原理和二进制一样,
先处理好乘0~9次的矩阵,每次p除以10,ans变成ans的十次方乘上原矩阵的v[i]次,v[i]是第i位的数字。
然后这题还要使用一些高级的卡常技巧,比如手打矩阵乘法之类。
顺便,这题1A感觉胖胖QWQ
代码:
/*************************************************************
Problem: bzoj 3286 Fibonacci矩阵
User: fengyuan
Language: C++
Result: Accepted
Time: 10696 ms
Memory: 12952 kb
Submit_Time: 2017-12-27 14:30:20
*************************************************************/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cctype>
using namespace std;
typedef long long LL;
const int LEN = 1000010;
const int MOD = 2012182013;
struct Bignum{
int v[LEN], len;
inline void read() {
char ch = getchar();
for(; !isdigit(ch); ch = getchar());
len = 0;
for(; isdigit(ch); ch = getchar()) v[++ len] = ch-'0';
for(int i = 1; i <= len/2; i ++) swap(v[i], v[len-i+1]);//个位在前,数位从低到高
}
inline void dec() {//减一
v[1] --;
for(int i = 1; i <= len; i ++)
if(v[i] < 0) v[i] += 10, v[i+1] --;
else break;
while(len && v[len] == 0) len --;
}
}n, m;
struct Matrix{
//矩阵本来是3*3的,考虑到最后一列基本没用,于是压成2列
LL v11, v12, v21, v22, v31, v32;
inline Matrix() {}
inline Matrix(int x) { (*this).set(x); }
inline void set(int x) {
v11 = v12 = v21 = v22 = v31 = v32 = 0;
if(x) v11 = v22 = 1;//单位矩阵
}
inline void build(int a, int b, int c) {
v11 = 0, v21 = 1, v31 = 0;
v12 = a, v22 = b, v32 = c;
}
Matrix operator * (Matrix &x) {
//优化常数,手打矩阵乘法
Matrix ans;
ans.v11 = (v11*x.v11+v12*x.v21)%MOD;
ans.v12 = (v11*x.v12+v12*x.v22)%MOD;
ans.v21 = (v21*x.v11+v22*x.v21)%MOD;
ans.v22 = (v21*x.v12+v22*x.v22)%MOD;
ans.v31 = (v31*x.v11+v32*x.v21+x.v31)%MOD;
ans.v32 = (v31*x.v12+v32*x.v22+x.v32)%MOD;
return ans;
}
}ret, ans, M1, M2;
LL a, b, c, d, e, f;
inline LL get()
{
char ch = getchar(); LL x = 0;
for(; !isdigit(ch); ch = getchar());
for(; isdigit(ch); ch = getchar()) x = (x*10+ch-'0')%MOD;
return x;
}
//每一位单独用二进制计算
inline Matrix ksm2(Matrix x)
{
int p = 10; Matrix ret(1);
while(p) {
if(p&1) ret = ret*x;
x = x*x; p >>= 1;
} return ret;
}
//十进制版矩阵快速幂,原理和二进制的差不多
inline Matrix ksm10(Matrix x, Bignum p)
{
Matrix ans(1);
Matrix fac[10]; fac[0].set(1);
for(int i = 1; i <= 9; i ++) fac[i] = fac[i-1]*x;//先处理好乘0~9次的矩阵
for(int i = p.len; i >= 1; i --)
ans = ksm2(ans)*fac[p.v[i]];
return ans;
}
int main()
{
n.read(); m.read();
a = get(); b = get(); c = get(); d = get(); e = get(); f = get();
M1.build(a, b, c); M2.build(d, e, f);
m.dec(); m.dec(); n.dec();
ret = ksm10(M1, m);//先计算到第一行最后一个数
ans = ksm10(ret*M2*M2, n)*ret;//计算到最后一行第一个数,再计算到最后一行最后一个数
printf("%lld\n", (ans.v12+ans.v22+ans.v32)%MOD);
return 0;
}