欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ3286


题意概括

n,m,a,b,c,d,e,f<=10^1000000


题解

  神奇的卡常题目。

  在此感谢"zhouzixuan"——bzoj 3286: Fibonacci矩阵

  学习他,才15秒卡过此题。

  这题的做法应该很明显的,学过矩阵快速幂的大概几眼就看出来了。

  对于每一行的转移,是相同的,所以矩阵快速幂可以搞定行与行之间的转移。

  然后对于某一行,其实大部分的转移是和abc有关的,同理也可用矩阵快速幂搞定。

  但是如果折半的话,矩阵快速幂的复杂度为log2(n)*len(n)   (高精度运算复杂度)

  要TLE。

  然后我们发现,如果10位10位走,就不用跑高精度了。那么时间复杂度理论上就可以过去了。

  但是这题神坑。

  卡常!!!!!!!

  那么,我们研究矩阵,发现,我们构造的矩阵,有一列(或者一行)的3个数的值总是不变的。

  那么,我们可以减少循环??

  然后,去掉循环,手写9个运算式又可以省去循环变量的几个运算的复杂度。

  然后,仍然不够。我们发现数组访问有点慢,那么我们把数组去掉,改成一个一个的变量。

  这样大概可以快上4倍。

  然后,我们发现之前的那3个不变的也没用了,直接不运算了,其余的按照原先的运算,其中涉及之前的那3个的就把变量名改成值就可以了。

  然后发现还是TLE了。

  您千万不要气馁。

  对于矩阵快速幂中,我原先的版本是这样的:

Mat MatPow(Mat x,int *v,int len){
Mat ans(1),xx;
for (int i=1;i<=len;i++){
for (int j=v[i];j--;)
ans=ans*x;
xx=x=x*x,x=x*x,x=x*x,x=x*xx;
}
return ans;
}

  其实,这个时候,我们不仅要在x上面花时间,又要在ans上花时间,所以,我们要想办法卡。

  事实上,我们可以这样:(省掉了约1/3的时间)

  

inline Mat MatPow(Mat x,int *v,int len){
Mat ans(1),xx;
Mat fac[10];
fac[0].set(1);
for (int i=1;i<=9;i++)
fac[i]=fac[i-1]*x;
for (int i=len;i>=1;i--)
ans=MatPow(ans)*fac[v[i]];
return ans;
}

  

  然后我就过去了。(心)累死了。


update 2017-12-22

在写BZOJ3240的时候,突然发现我当初在写最后的MatPow的时候,有重复计算。然后舍去了重复计算,卡掉了1/3的常数,现在是10秒了。


代码

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long LL;
const int mod=2012182013;
struct BigInt{
static const int MaxL=1000005;
int v[MaxL],len;
inline bool isd(char ch){return '0'<=ch&&ch<='9';}
inline void read(){
len=0;
char ch=getchar();
while (!isd(ch))
ch=getchar();
while (isd(ch))
v[++len]=ch-48,ch=getchar();
for (int i=1;i<=len/2;i++)
swap(v[i],v[len+1-i]);
}
inline void minus(){
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])
len--;
}
};
inline bool isd(char ch){return '0'<=ch&&ch<='9';}
inline LL getMODed(){
char ch=getchar();
while (!isd(ch))
ch=getchar();
LL res=0;
while (isd(ch))
res=(res*10+ch-48)%mod,ch=getchar();
return res;
}
struct Mat{
LL v11,v12,v21,v22,v31,v32;
inline Mat (){}
inline Mat (int x){(*this).set(x);}
inline void set(int x){
v11=v12=v21=v22=v31=v32=0;
if (x==1)
v11=v22=1;
}
inline void build(int a,int b,int c){
v11=0,v12=a;
v21=1,v22=b;
v31=0,v32=c;
}
inline Mat operator * (Mat &b){
Mat ans;
ans.v11=(v11*b.v11+v12*b.v21)%mod;
ans.v12=(v11*b.v12+v12*b.v22)%mod;
ans.v21=(v21*b.v11+v22*b.v21)%mod;
ans.v22=(v21*b.v12+v22*b.v22)%mod;
ans.v31=(v31*b.v11+v32*b.v21+b.v31)%mod;
ans.v32=(v31*b.v12+v32*b.v22+b.v32)%mod;
return ans;
}
};
inline Mat MatPow(Mat x){
Mat ans(1);
for (int y=10;y;y>>=1,x=x*x)
if (y&1)
ans=ans*x;
return ans;
}
inline Mat MatPow(Mat x,int *v,int len){
Mat ans(1),xx;
Mat fac[10];
fac[0].set(1);
for (int i=1;i<=9;i++)
fac[i]=fac[i-1]*x;
for (int i=len;i>=1;i--)
ans=MatPow(ans)*fac[v[i]];
return ans;
}
LL a,b,c,d,e,f;
BigInt n,m;
Mat Mx,My,en,res;
int main(){
n.read(),m.read();
a=getMODed(),b=getMODed(),c=getMODed();
d=getMODed(),e=getMODed(),f=getMODed();
Mx.build(a,b,c),My.build(d,e,f);
m.minus(),m.minus(),n.minus();
res=MatPow(Mx,m.v,m.len);
en=MatPow(res*My*My,n.v,n.len)*res;
printf("%lld",(en.v12+en.v22+en.v32)%mod);
return 0;
}

  

BZOJ3286 Fibonacci矩阵 矩阵 快速幂 卡常的更多相关文章

  1. BZOJ3240 [Noi2013]矩阵游戏 矩阵 快速幂 卡常

    原文链接http://www.cnblogs.com/zhouzhendong/p/8084891.html 题目传送门 - BZOJ3240 题意概括 F[1][1]=1F[i,j]=a*F[i][ ...

  2. Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂)

    Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂) Description 广义的斐波那契数列是指形如\[A_n=p*a_{n-1}+q*a_{n-2}\]的数列.今给定数列的两系数p和q, ...

  3. 洛谷 P4910 帕秋莉的手环 矩阵乘法+快速幂详解

    矩阵快速幂解法: 这是一个类似斐波那契数列的矩乘快速幂,所以推荐大家先做一下下列题目:(会了,差不多就是多倍经验题了) 注:如果你不会矩阵乘法,可以了解一下P3390的题解 P1939 [模板]矩阵加 ...

  4. Qbxt 模拟赛 Day4 T2 gcd(矩阵乘法快速幂)

    /* 矩阵乘法+快速幂. 一开始迷之题意.. 这个gcd有个规律. a b b c=a*x+b(x为常数). 然后要使b+c最小的话. 那x就等于1咯. 那么问题转化为求 a b b a+b 就是斐波 ...

  5. 矩阵乘法快速幂 codevs 1732 Fibonacci数列 2

    1732 Fibonacci数列 2  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 在“ ...

  6. [codevs]1250斐波那契数列<矩阵乘法&快速幂>

    题目描述 Description 定义:f0=f1=1, fn=fn-1+fn-2(n>=2).{fi}称为Fibonacci数列. 输入n,求fn mod q.其中1<=q<=30 ...

  7. 【BZOJ-1009】GT考试 KMP+DP+矩阵乘法+快速幂

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2745  Solved: 1694[Submit][Statu ...

  8. 矩阵乘法快速幂 codevs 1574 广义斐波那契数列

    codevs 1574 广义斐波那契数列  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond   题目描述 Description 广义的斐波那契数列是指形如 ...

  9. BZOJ-1875 HH去散步 DP+矩阵乘法快速幂

    1875: [SDOI2009]HH去散步 Time Limit: 20 Sec Memory Limit: 64 MB Submit: 1196 Solved: 553 [Submit][Statu ...

随机推荐

  1. 【原创】大数据基础之Hive(4)hive元数据库核心表结构

    1 dbs +-------+-----------------------+----------------------------------------------+------------+- ...

  2. Android gradle provided、implementation等指令注意点

    其实这类文章博客网上一搜一大堆,但有些地方可能说的不太清楚(都一样的内容,抄袭太严重),这里只是做个精简的总结和一些其他地方没提到的点. 一.Android Studio 3.0开始使用了新的指令,原 ...

  3. AGC 014 E Blue and Red Tree [树链剖分]

    传送门 思路 官方题解是倒推,这里提供一种正推的做法. 不知道你们是怎么想到倒推的--感觉正推更好想啊QwQ就是不好码 把每一条红边,将其转化为蓝树上的一条路径.为了连这条红边,需要保证这条路径仍然完 ...

  4. Confluence 6 编辑和删除用户宏

    编辑一个用户宏 希望对一个用户宏进行编辑: 进入  > 基本配置(General Configuration) > 用户宏(User Macros) 在相关的宏的边上,单击 编辑(Edit ...

  5. iframe与主框架跨域相互访问方法

    iframe 与主框架相互访问方法  http://blog.csdn.net/fdipzone/article/details/17619673/ 1.同域相互访问 假设A.html 与 b.htm ...

  6. ionic3 点击输入 框弹出白色遮罩 并把 界面顶到上面

    这个蛋疼 问题 ,在android 上面遇到这种情况 ,键盘弹出的时候 总有一个白色的遮罩在后面出现,网上查了很久都没发现原因. 偶然发现一个方法 ,试下了下 问题解决了. 代码如下: IonicMo ...

  7. maven添加镜像与常用配置

    maven解压后conf文件夹有个 settings.xml 在这个文件中可以配置我们的maven 配置镜像: 找到<mirrors></mirrors>找到这个节点在节点中添 ...

  8. LeetCode(84): 柱状图中最大的矩形

    Hard! 题目描述: 给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . 求在该柱状图中,能够勾勒出来的矩形的最大面积. 以上是柱状图的示例,其中每个柱子的宽度 ...

  9. Question Of AI Model Training

    1 模型训练基本步骤 准备原始数据,定义神经网络结构及前向传播算法 定义loss,选择反向传播优化算法 生成Session,在训练数据进行迭代训练,使loss到达最小 在测试集或者验证集上对准确率进行 ...

  10. Niagara 泵阀

    1.泵阀系统 2.Niagara 每次在启动workbench的时候安装一下daemon,后启动platform 启动station的时候,当station的status变成Running之后启动