hdu 1588(Fibonacci矩阵求和)
题目的大意就是求等差数列对应的Fibonacci数值的和,容易知道Fibonacci对应的矩阵为[1,1,1,0],因为题目中f[0]=0,f[1]=1,所以推出最后结果f[n]=(A^n-1).a,所以 f(g(i))= f(k*i+b)= (A^(k*i+b-1)).a,i从 0取到 n-1,取出公因式 A^(b-1)(因为矩阵满足分配率),然后所求结果可化为 A^(b-1) * (A^0 + A^k + A^2k +....+ A^(n-1)k),化到这里后难点就是求和了,一开始我尝试暴力求和(每个A^k可以用快速幂求出,logn级别),即O(n)的做法,结果TLE了,预料之中,这时我竟傻乎乎地套用等比数列求和公式,即(A^nk -A^0) /(A^k -E),按比例放大再相减是没错,问题是不是简单的相除……总之思路应该是错的了,后来看别人的博客后才知道原来可以用二分来求和的,即 A^0 + A^k + A^2k +....+ A^(n-1)k = (A^0 + A^k + A^2k +...+ A^(n/2-1)k) *(E + A^(n/2)k),递归来求和,处理好 n的奇偶性即可,但我还是调试了好久,就因为在一些细节问题上出错却检查不出来,下面附上代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef long long LL;
LL mod= ; //初不初始化都没问题,只是为了防止忘记读入时产生的异常退出 struct matrix{
LL a,b,c,d;
matrix(LL a=, LL b=, LL c=, LL d=): a(a),b(b),c(c),d(d) {}
matrix operator +(const matrix &m2){
return matrix((a+m2.a)%mod,(b+m2.b)%mod,(c+m2.c)%mod,(d+m2.d)%mod);
}
matrix operator *(const matrix &m2){
return matrix((a*m2.a%mod+b*m2.c%mod)%mod, (a*m2.b%mod+b*m2.d%mod)%mod, (c*m2.a%mod+d*m2.c%mod)%mod, (c*m2.b%mod+d*m2.d%mod)%mod);
}
//一开始等比数列求和的思路要用到除法,后来才发现是错的,不过也不删了,就放在这吧
matrix operator /(const matrix &m2){
//二维求逆很好求的
matrix inv= matrix(m2.d,-m2.b,-m2.c,m2.a);
LL tmp= m2.a*m2.d-m2.b*m2.c;
return matrix((a*inv.a/tmp%mod+b*inv.c/tmp%mod)%mod, (a*inv.b/tmp%mod+b*inv.d/tmp%mod)%mod, (c*inv.a/tmp%mod+d*inv.c/tmp%mod)%mod, (c*inv.b/tmp%mod+d*inv.d/tmp%mod)%mod);
}
};
// A为 Fibonacci矩阵,E为单位矩阵,设为全局变量更方便一些
matrix A(,,,),E(,,,); //简单的快速幂
matrix quick_mod(matrix m, LL b){
if(b==-) return matrix(,,,-);
//若指数为-1,返回矩阵 A^-1,相当于A^1的逆(算了好久T.T)
matrix res(E); //res一开始为单位矩阵
while(b){
if(b&) res= res*m;
m= m*m;
b>>=;
}
return res;
} //二分法计算 A^0 + A^k + A^2k +....+ A^(n-1)k 的和
//即 sum =(A^0 + A^k + A^2k +...+ A^(n/2-1)k) *(E + A^(n/2)k),分治的思想
matrix quick_sum(LL k, LL n){
if(n==) return E; //若 n为1,即计算 A^0,此时返回的是 E!而不是 A!一开始没想到错在这里,卡了好久 T.T
if(n%==) return quick_sum(k,n/)*(E+quick_mod(A,(n/)*k));
//else return quick_sum(k,(n-1)/2)*(E+quick_mod(A,((n-1)/2)*k))*quick_mod(A,(n-1)*k);
else return quick_sum(k,n-) + quick_mod(A,(n-)*k);
//这样的写法比起上一行的虽然会多一次调用函数的开销,但可读性增强,代码逻辑更清晰
} int main()
{
//freopen("1588in.txt","r",stdin);
LL k,b,n;
while(~scanf("%I64d%I64d%I64d%I64d",&k,&b,&n,&mod)){
//最后的结果就是 A^b-1 *(A0 + A^k + A^2k +...+ A(n-1)k) 的 a
matrix ans= quick_mod(A,b-) * quick_sum(k,n);
printf("%I64d\n",ans.a);
}
return ;
}
hdu 1588(Fibonacci矩阵求和)的更多相关文章
- HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和)
HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出 ...
- HDU 1588 Gauss Fibonacci(矩阵快速幂)
Gauss Fibonacci Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDU 3117 Fibonacci Numbers(围绕四个租赁斐波那契,通过计++乘坐高速动力矩阵)
HDU 3117 Fibonacci Numbers(斐波那契前后四位,打表+取对+矩阵高速幂) ACM 题目地址:HDU 3117 Fibonacci Numbers 题意: 求第n个斐波那契数的 ...
- hdu 3117 Fibonacci Numbers 矩阵快速幂+公式
斐波那契数列后四位可以用快速幂取模(模10000)算出.前四位要用公式推 HDU 3117 Fibonacci Numbers(矩阵快速幂+公式) f(n)=(((1+√5)/2)^n+((1-√5) ...
- poj 1195:Mobile phones(二维树状数组,矩阵求和)
Mobile phones Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 14489 Accepted: 6735 De ...
- poj 1195:Mobile phones(二维线段树,矩阵求和)
Mobile phones Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 14391 Accepted: 6685 De ...
- UVA 11149-Power of Matrix(等比矩阵求和)
给定一个矩阵A 要求A + A^2 + A^3 +…. A^k: 对于到n的等比矩阵求和 如果n是偶数: 如果n是奇数: #include<stdio.h> #include<s ...
- BZOJ3286 Fibonacci矩阵 矩阵 快速幂 卡常
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3286 题意概括 n,m,a,b,c,d,e,f<=10^1000000 题解 神奇的卡常题目 ...
- BZOJ 2901: 矩阵求和
2901: 矩阵求和 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 411 Solved: 216[Submit][Status][Discuss] ...
随机推荐
- linux socket高性能服务器处理框架
这个博客很多东西 http://blog.csdn.net/luozhonghua2014/article/details/37041765 思考一种高性能的服务器处理框架 1.首先需要一个内存池 ...
- CSUFT 1005 Coffin Tiles
1005: Coffin Tiles Time Limit: 1 Sec Memory Limit: 128 MB Submit: 2 Solved: 2 Description ...
- 将本地项目上传到Github
将本地项目上传到Github 转载请注明出自天外归云的博客. 前提 已经下载了Git到本地. 创建Repository 首先登陆我的Github页面,在Repositories中New一个并起Repo ...
- 【Java】如何检测、替换4个字节的utf-8编码(此范围编码包含emoji表情)
> 参考的优秀文章 1.十分钟搞清字符集和字符编码 2.Java中byte与16进制字符串的互相转换 3.[异常处理]Incorrect string value: '\xF0\x90\x8D\ ...
- Java CSV操作(导出和导入)
Java CSV操作(导出和导入) CSV是逗号分隔文件(Comma Separated Values)的首字母英文缩写,是一种用来存储数据的纯文本格式,通常用于电子表格或数据库软件.在 CSV文件 ...
- 求数组中的最小子数组,时间复杂度o(n),java
石家庄铁道大学 信1405-1 班 唐炳辉 题目:给定一个整数数组,找到一个具有最小和的子数组.返回其最小和. 设计思路:两个变量 ,一个记录当前并入的数组的值,另外一个记录所算过得最大的数组的值,当 ...
- C#打开指定路径文件对话框
private string OpenFileDlog(string DeafultDir) { OpenFileDialog Ofd = new OpenFileDialog(); Ofd.AddE ...
- BZOJ 1006 神奇的国度(弦图的染色数)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1006 题意:给定一个弦图,求最小染色数.就是用最小数目的颜色进行染色使得任意两个相邻的节 ...
- C# 多线程 Invoke BeginInvoke
Invoke在线程中等待Dispatcher调用指定方法,完成后继续下面的操作. BeginInvoke不必等待Dispatcher调用制定方法,直接继续下面的操作. 来自:百度知道 这个在线程中操作 ...
- 【转载】ODBC, OLEDB, ADO, ADO.Net的演化简史
原文:ODBC, OLEDB, ADO, ADO.Net的演化简史 1.演变历史 它们是按照这个时间先后的顺序逐步出现的,史前->ODBC->OLEDB->ADO->ADO.N ...