BZOJ3286 Fibonacci矩阵 矩阵 快速幂 卡常
欢迎访问~原文出处——博客园-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矩阵 矩阵 快速幂 卡常的更多相关文章
- BZOJ3240 [Noi2013]矩阵游戏 矩阵 快速幂 卡常
原文链接http://www.cnblogs.com/zhouzhendong/p/8084891.html 题目传送门 - BZOJ3240 题意概括 F[1][1]=1F[i,j]=a*F[i][ ...
- Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂)
Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂) Description 广义的斐波那契数列是指形如\[A_n=p*a_{n-1}+q*a_{n-2}\]的数列.今给定数列的两系数p和q, ...
- 洛谷 P4910 帕秋莉的手环 矩阵乘法+快速幂详解
矩阵快速幂解法: 这是一个类似斐波那契数列的矩乘快速幂,所以推荐大家先做一下下列题目:(会了,差不多就是多倍经验题了) 注:如果你不会矩阵乘法,可以了解一下P3390的题解 P1939 [模板]矩阵加 ...
- Qbxt 模拟赛 Day4 T2 gcd(矩阵乘法快速幂)
/* 矩阵乘法+快速幂. 一开始迷之题意.. 这个gcd有个规律. a b b c=a*x+b(x为常数). 然后要使b+c最小的话. 那x就等于1咯. 那么问题转化为求 a b b a+b 就是斐波 ...
- 矩阵乘法快速幂 codevs 1732 Fibonacci数列 2
1732 Fibonacci数列 2 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 在“ ...
- [codevs]1250斐波那契数列<矩阵乘法&快速幂>
题目描述 Description 定义:f0=f1=1, fn=fn-1+fn-2(n>=2).{fi}称为Fibonacci数列. 输入n,求fn mod q.其中1<=q<=30 ...
- 【BZOJ-1009】GT考试 KMP+DP+矩阵乘法+快速幂
1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2745 Solved: 1694[Submit][Statu ...
- 矩阵乘法快速幂 codevs 1574 广义斐波那契数列
codevs 1574 广义斐波那契数列 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 广义的斐波那契数列是指形如 ...
- BZOJ-1875 HH去散步 DP+矩阵乘法快速幂
1875: [SDOI2009]HH去散步 Time Limit: 20 Sec Memory Limit: 64 MB Submit: 1196 Solved: 553 [Submit][Statu ...
随机推荐
- lua内存监测和回收
以下来自书籍<Cocos2d-x之Lua核心编程> 1.----------------------------------------- 若想查看程序当前的内存占用情况,可以使用Lua提 ...
- PYTHON- 操作系统和python程序
操作系统基础 应用程序的启动:(重点!!!) python解释器安装,多版本共存 执行python程序的两种方式 运行一个python程序经历的三个阶段(重要) python 的内存管理 ====== ...
- Django项目的创建及基本使用
安装步骤 Django是Python进行Web开发的框架,目前应用比较广泛.使用python进行Web开发,能够很快的搭建所需的项目,可以运用于原型开发,也可以部署到实际的应用环境. 使用Django ...
- day04 运算符 流程控制 (if while/of)
1. 运算符算数运算符 + - * / int / float :数字类型 # print(10 + 3.1)# print(10 / 3)# print(10 // 3)# print(10 % 3 ...
- LeetCode(125):验证回文串
Easy! 题目描述: 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例 1: 输入: "A man, ...
- 浅谈js的join()方法
简单描述:今天看同事的代码,看js的时候,看到了一个join()方法,我从来都没有用过,就查了查,第一次用就记录一下 正经的: 定义和用法 join() 方法用于把数组中的所有元素放入一个字符串. 元 ...
- input标签 disabled 和 readonly的区别
需求描述:今天提交代码,老大审了一下,给我指出了一个改正的地方,XXX的详细信息页面(不是修改页面) input的内容是不能改的,给我指出的时候,我立马就知道了这个该怎么改了,加个readonly不就 ...
- noip 2018.10.14 模拟赛 砍树
数学问题... 根据题意,有: 移项,整理,得: 记 于是 那么 可以看到,最多只会有2*个取值(显而易见) 于是对应的,可能产生效果的d也只会有个,于是我们把他们找出来,扔进一个数组里然后排序,去重 ...
- Java 获取图片的大小、宽、高
参考:https://www.cnblogs.com/hongten/archive/2012/11/26/hongten_java_ImageReader_BufferedImage.html im ...
- net core 使用 rabbitmq
windows环境安装: https://www.cnblogs.com/ericli-ericli/p/5902270.html .NET Core 使用RabbitMQ https://www.c ...