FZU Problem 2198 快来快来数一数(矩阵快速幂 卡常数 +优化)
题目链接:http://acm.fzu.edu.cn/problem.php?pid=2198
Problem Description
n个六边形排成一行,相邻两个六边形共用一条边,如下图所示:
记这个图形的生成树个数为t(n)(由于每条边都是不同的,不存在同构的问题)。那么t(1)=6,t(2)=35……
给出n,求mod 1000000007
Input
第一行给出数据组数T。
之后每一行给出一个正整数n。
T大约为50000,n<=10^18。
Output
每组数据输出一行答案。
Sample Input
Sample Output
Source
FOJ有奖月赛-2015年10月
PS:
很容易写出通项公式为:
a[i] = 6*a[i-1] - a[i-2] +1;
但是这题的n很大T也很大!会卡常数!
普通的矩阵快速幂是会超时的;
这时就需要用到快速幂的优化了!
但是我直接在普通的矩阵快速幂上加了优化,还是会超时,
在提交了多次后,终于有一次过了而且时间是恰好1000ms!
然后再用相同的代码提交就是T!
下面给出一个矩阵快速幂优化的模板;
用这个模板,时间直接减少的500+ms!
代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const LL mod = 1000000007;struct Matrix
{int row,col;LL m[4][4];void init(int row, int col){this->row = row;this->col = col;for(int i = 0; i < row; ++i)for(int j = 0; j < col; ++j)m[i][j] = 0;}
} A, pp[66], ans;Matrix operator*(const Matrix & a, const Matrix& b)
{Matrix res;res.init(a.row,b.col);for(int k = 0; k < a.col; ++k){for(int i = 0; i < res.row; ++i){if(a.m[i][k] == 0 ) continue;for(int j = 0; j < res.col; ++j){if(b.m[k][j] == 0 ) continue;res.m[i][j] = (a.m[i][k]*b.m[k][j] + res.m[i][j])%mod;}}}return res;
}
void init()
{Matrix qq;A.init(3,1);A.m[0][0] = 7;A.m[1][0] = 1;A.m[2][0] = 1;qq.init(3,3);qq.m[0][0] = 6;qq.m[0][1] = -1;qq.m[0][2] = 1;qq.m[1][0] = 1;qq.m[2][2] = 1;pp[0] = qq;for(int i = 1; i < 64; i++)pp[i] = pp[i-1] * pp[i-1];
}void Cal(LL a)
{for(int i=0; a; i++,a>>=1){if(a&1){ans = pp[i]*ans;}}return ;
}int main()
{int T;LL n;init();scanf("%d",&T);while(T--){scanf("%I64d",&n);ans = A;Cal(n-1);printf("%I64d\n",(ans.m[0][0]-1+mod)%mod);}
}
最后给出普通的矩阵快速幂+优化代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL __int64
struct Matrix
{LL m[4][4];
} I,A,B,T;
LL n, c;
int ssize = 3;
const LL mod = 1000000007;Matrix Mul(Matrix a,Matrix b)
{int i, j, k;Matrix c;for(i = 1; i <= ssize; i++){for(j = 1; j <= ssize; j++){c.m[i][j]=0;for(k = 1; k <= ssize; k++){c.m[i][j]+=(a.m[i][k]*b.m[k][j]);c.m[i][j]%=mod;}}}return c;
}Matrix quickpagow(LL n)
{memset(I.m,0,sizeof(I.m));for(int i = 1; i <= ssize; i++){//单位矩阵I.m[i][i]=1;}Matrix m = A, b = I;while(n > 0){if(n & 1)b = Mul(b,m);n = n >> 1;m = Mul(m,m);}return b;
}
int main()
{memset(A.m,0,sizeof(A.m));memset(B.m,0,sizeof(B.m));A.m[1][1] = 6;//初始化等比矩阵A.m[1][2] = -1;A.m[1][3] = A.m[2][1] = A.m[3][3] = 1;B.m[1][1] = 7;B.m[2][1] = 1;B.m[3][1] = 1;Matrix haha[80];haha[1] = A;for(int i = 2; i < 70; i++){haha[i] = Mul(haha[i-1], haha[i-1]);}int t;scanf("%d",&t);while(t--){scanf("%I64d",&n);if(n==1){printf("6\n");continue;}if(n==2){printf("41\n");continue;}Matrix C;memset(C.m,0,sizeof(C.m));n--;for(int i = 1; i <= ssize; i++){C.m[i][i] = 1;}for(int i = 1; n; i++,n>>=1){if(n&1){C = Mul(C,haha[i]);}}T = Mul(C,B);printf("%I64d\n",(T.m[1][1]-1+mod)%mod);}return 0;
}
FZU Problem 2198 快来快来数一数(矩阵快速幂 卡常数 +优化)相关推荐
- 数绵羊(矩阵快速幂)
问题描述 一个数:1234567891011121314151617181920-,数到了N,那么形成的这个数字除以1000000007的余数是多少呢? 输入描述 一行,一个整数N,如题目描述 输出描 ...
- BC#29A:GTY's math problem(math) B:GTY's birthday gift(矩阵快速幂)
A: HDU5170 这题让比较a^b与c^d的大小.1<=a,b,c,d<=1000. 显然这题没法直接做,要利用对数来求,但是在math库中有关的对数函数返回的都是浮点数,所以这又要涉 ...
- Fzu 2198 快来快来数一数【矩阵快速幂】
Problem 2198 快来快来数一数 Accept: 218 Submit: 704 Time Limit: 1000 mSec Memory Limit : 65536 KB P ...
- foj2198 Problem 2198 快来快来数一数 dp 矩阵快速幂
Problem 2198 快来快来数一数 Accept: 67 Submit: 194 Time Limit: 1000 mSec Memory Limit : 65536 KB Problem De ...
- DUToj1085 Water Problem(矩阵快速幂)
Problem I: Water Problem Time Limit:3000/1000 MS (Java/Others) Memory Limit:163840/131072 KB (Java ...
- LightOJ 1070 Algebraic Problem (推导+矩阵快速幂)
题目链接:LightOJ 1070 Algebraic Problem 题意:已知a+b和ab的值求a^n+b^n.结果模2^64. 思路: 1.找递推式 得到递推式之后就是矩阵快速幂了 注意:模2^ ...
- 2015多校10 1006.CRB and Puzzle HDU5411(邻接矩阵求k长路条数,矩阵快速幂
题意:有若干字符,现在要把它们连成一个字符串,每种字符后面只能接特定种类的字符,现在询问能连接出的长度小于等于m的字符串有多少种. 思路:我们可以把这个转移关系看成一个图,如果字符a后面可以接b,那么 ...
- A Simple Math Problem(矩阵快速幂)
Lele now is thinking about a simple function f(x). If x < 10 f(x) = x. If x >= 10 f(x) = a0 * ...
- 【HDU - 1757】A Simple Math Problem (矩阵快速幂)
题干: Lele now is thinking about a simple function f(x). If x < 10 f(x) = x. If x >= 10 f(x) = ...
- leetcode509. 斐波那契数(矩阵快速幂)
斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列.该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和.也就是: F(0) = 0, F(1) = 1 F(N) = F( ...
最新文章
- 中文文本中的关键字提取算法总结
- sentinel使用(结合OpenFeign)
- LUA学习之路--初识LUA
- java继承与多态_Java继承与多态
- Fisher–Yates shuffle 算法
- 响应对象Response
- python中星号数字乘字符串_Python系列-数字和字符串
- python的编码类型转换
- 执行import xlrd,报错ModuleNotFoundError: No module named 'xlrd'
- indy9 indy10 MD5 实现方法
- vue怎么实现手风琴效果_Vue中使用v-for制作动态手风琴效果
- paip.调试js 查看元素事件以及事件断点
- setcpu_SetCpu Android超频工具
- DevOps落地实践:BAT系列:敏捷看板:iCafe vs Tapd
- java微信token验证_JAVA折腾微信公众平台(Token验证)
- 【避坑 超详细】Ubuntu使用python的selenium以及chrome模拟真实浏览器访问网页
- 计算机网络之七层网络模型
- Mybatis完整版(二)
- 百度云管家下载大文件龟速问题解决
- linux和windows双系统传文件夹,如何linux和windows双系统互拷文件?