Accept: 204    Submit: 627

Time Limit: 1000 mSec    Memory Limit : 65536 KB

 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

2212345678987654321

 Sample Output

41733521876

 Source

这题用矩阵快速幂做,先用dp[i][f]表示处理到第i个矩形,第i个矩形右边那条边会不会不去掉的方案数,那么dp[i][1]=d[i-1][0]+dp[i-1][1],dp[i][0]=4*dp[i-1][1]+5*dp[i-1][0].

我们可以构造矩阵【dp[i][1],dp[i][0],sum[i]  】*A=【dp[i+1][1],dp[i+1][0],sum[i+1]  】.
                   1 4 5
容易求出A=1 5 6
                   0 0 1
然后用矩阵快速幂就行了,这里要注意,这题卡常数,所以要先初始化64个矩阵的乘方,然后再算,而且注意取模不能取太多,不然会超时。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
typedef unsigned long long ll;
#define inf 0x7fffffff
#define pi acos(-1.0)
#define MOD 1000000007
struct matrix{
int n,m,i;
ll data[3][3];
}a,b,c,d[99],t; matrix multi(matrix &a,matrix &b){
matrix ans;
memset(ans.data,0,sizeof(ans.data));
ans.data[0][0]=(ans.data[0][0]+a.data[0][0]*b.data[0][0]);
ans.data[0][1]=(ans.data[0][1]+a.data[0][0]*b.data[0][1]);
ans.data[0][2]=(ans.data[0][2]+a.data[0][0]*b.data[0][2]);
ans.data[0][0]=(ans.data[0][0]+a.data[0][1]*b.data[1][0]);
ans.data[0][1]=(ans.data[0][1]+a.data[0][1]*b.data[1][1]);
ans.data[0][2]=(ans.data[0][2]+a.data[0][1]*b.data[1][2]);
ans.data[0][0]=(ans.data[0][0]+a.data[0][2]*b.data[2][0])%MOD;
ans.data[0][1]=(ans.data[0][1]+a.data[0][2]*b.data[2][1])%MOD;
ans.data[0][2]=(ans.data[0][2]+a.data[0][2]*b.data[2][2])%MOD; ans.data[1][0]=(ans.data[1][0]+a.data[1][0]*b.data[0][0]);
ans.data[1][1]=(ans.data[1][1]+a.data[1][0]*b.data[0][1]);
ans.data[1][2]=(ans.data[1][2]+a.data[1][0]*b.data[0][2]);
ans.data[1][0]=(ans.data[1][0]+a.data[1][1]*b.data[1][0]);
ans.data[1][1]=(ans.data[1][1]+a.data[1][1]*b.data[1][1]);
ans.data[1][2]=(ans.data[1][2]+a.data[1][1]*b.data[1][2]);
ans.data[1][0]=(ans.data[1][0]+a.data[1][2]*b.data[2][0])%MOD;
ans.data[1][1]=(ans.data[1][1]+a.data[1][2]*b.data[2][1])%MOD;
ans.data[1][2]=(ans.data[1][2]+a.data[1][2]*b.data[2][2])%MOD; ans.data[2][0]=(ans.data[2][0]+a.data[2][0]*b.data[0][0]);
ans.data[2][1]=(ans.data[2][1]+a.data[2][0]*b.data[0][1]);
ans.data[2][2]=(ans.data[2][2]+a.data[2][0]*b.data[0][2]);
ans.data[2][0]=(ans.data[2][0]+a.data[2][1]*b.data[1][0]);
ans.data[2][1]=(ans.data[2][1]+a.data[2][1]*b.data[1][1]);
ans.data[2][2]=(ans.data[2][2]+a.data[2][1]*b.data[1][2]);
ans.data[2][0]=(ans.data[2][0]+a.data[2][2]*b.data[2][0])%MOD;
ans.data[2][1]=(ans.data[2][1]+a.data[2][2]*b.data[2][1])%MOD;
ans.data[2][2]=(ans.data[2][2]+a.data[2][2]*b.data[2][2])%MOD;
return ans; /*
for(int i=0;i<3;i++){
for(int k=0;k<3;k++){
if(a.data[i][k]>0)
for(int j=0;j<3;j++){
ans.data[i][j]=(ans.data[i][j]+a.data[i][k]*b.data[k][j])%MOD;
}
}
}
return ans;
*/
} matrix fast_mod(ll n){
matrix ans;
ans.n=3;
ans.m=3;
memset(ans.data,0,sizeof(ans.data));
ans.data[0][0]=ans.data[1][1]=ans.data[2][2]=1;
int num=1;
while(n>0){
if(n&1){
ans=multi(ans,d[num]);
}
num++;
n>>=1;
}
printf("%I64d\n",(ans.data[0][2]+5*ans.data[1][2]+6*ans.data[2][2] )%MOD);
} void init()
{
int i,j;
d[1].n=d[1].m=3;
d[1].data[0][0]=1;
d[1].data[0][1]=4;
d[1].data[0][2]=5;
d[1].data[1][0]=1;
d[1].data[1][1]=5;
d[1].data[1][2]=6;
d[1].data[2][0]=0;
d[1].data[2][1]=0;
d[1].data[2][2]=1;
for(i=2;i<64;i++){
d[i]=multi(d[i-1],d[i-1]);
}
} int main()
{
ll n,m,i,j;
int T;
init();
scanf("%d",&T);
while(T--)
{
scanf("%I64d",&n);
if(n==0){
printf("0\n");
continue;
}
fast_mod(n-1);
}
return 0;
}

fzu2198 快来快来数一数的更多相关文章

  1. fzu Problem 2198 快来快来数一数 (快速幂+优化)

    题目链接: Problem  2198  快来快来数一数 题目描述: 给出n个六边形排成一排,a[i]代表i个六边形能组成的生成树个数,设定s[i]等于a[1]+a[2]+a[3]+....+a[i- ...

  2. OpenGL快问快答

    OpenGL快问快答 本文内容主要来自对(http://www.opengl.org/wiki/FAQ)的翻译,随机加入了本人的观点.与原文相比,章节未必完整,含义未必雷同,顺序未必一致.仅供参考. ...

  3. 快读&快写模板【附O2优化】

    快读&快写模板 快读快写,顾名思义,就是提升输入和输出的速度.在这里简单介绍一下几种输入输出的优劣. C++ cin/cout 输入输出:优点是读入的时候不用管数据类型,也就是说不用背scan ...

  4. P1908 逆序对——树状数组&离散化&快读快写の学习

    题目简述: 对于给定的一段正整数序列,逆序对就是序列中 a_i>a_jai​>aj​ 且 i<ji<j 的有序对. 输出序列中逆序对的数目. 知识补充: 树状数组: 这东西就是 ...

  5. HDU 1068 Girls and Boys(最大独立集合 = 顶点数 - 最大匹配数)

    HDU 1068 :题目链接 题意:一些男孩和女孩,给出一些人物关系,然后问能找到最多有多少个人都互不认识. 转换一下:就是大家都不认识的人,即最大独立集合 #include <iostream ...

  6. 卡特兰数 Catalan数 ( ACM 数论 组合 )

    卡特兰数 Catalan数 ( ACM 数论 组合 ) Posted on 2010-08-07 21:51 MiYu 阅读(13170) 评论(1)  编辑 收藏 引用 所属分类: ACM ( 数论 ...

  7. HDU 4160 Dolls (最小路径覆盖=顶点数-最大匹配数)

    Dolls Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...

  8. catalan 数——卡特兰数(转)

    Catalan数——卡特兰数 今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来后来查了下,原来是Catalan数.悲剧啊,现在整理一下 一.Catalan数的定义令h(1) ...

  9. html5 vedio 播放器,禁掉进度条快进快退事件

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. JS 实现计算一段文字中的字节数,字母数,数字数,行数,汉字数。

    看到了匹配,第一个想到了用正则表达式,哈哈,果然很方便.不过正则表达式高深莫测!我还没有研究明白啊..目前学了点皮毛.代码如下: <!DOCTYPE html PUBLIC "-//W ...

随机推荐

  1. 【SpringBoot1.x】SpringBoot1.x 启动配置原理 和 自定义starter

    SpringBoot1.x 启动配置原理 和 自定义starter 启动配置原理 本节源码 启动过程主要为: new SpringApplication(sources) 创建 SpringAppli ...

  2. Java JVM——9.方法区

    前言 方法区是运行时数据区的最后一个部分: 从线程共享与否的角度来看: 大家可能在这里有些疑惑,方法区和元空间的关系到底是怎样的?请往下看,下面会为大家解惑. 栈.堆.方法区的交互关系 下面就涉及了对 ...

  3. 日常采坑:.NetCore上传大文件

    一..NetCore上传大文件 .NetCore3.1 webapi 本地测试上传时,遇到一个坑,大点的文件直接失败,根本不走控制器方法. 二.大文件上传配置 IFormFile方式,vs IIS E ...

  4. 【Linux】大于2T的磁盘怎么分区?

    环境CentOS7.1 2.9t磁盘 fdisk 只能分区小于2t的磁盘,大于2t的话,就要用到parted 1,将磁盘上原有的分区删除掉: 进入:#parted   /dev/sdb 查看:(par ...

  5. kubernets之服务发现

    一  服务与pod的发现 1.1  服务发现pod是很显而易见的事情,通过简称pod的标签是否和服务的标签一致即可,但是pod是如何发现服务的呢?这个问题其实感觉比较多余,但是接下来你就可能不这么想了 ...

  6. 使用memory_profiler异常

    在使用memory_profiler模块0.55.0版本执行命令诊断程序内存用量时,遇到下面错误: C:\Users\Chen\Desktop\python_doc\第四模块课件>python ...

  7. 训练分类器 - 基于 PyTorch

    训练分类器 目前为止,我们已经掌握了如何去定义神经网络.计算损失和更新网络中的权重. 关于数据 通常来讲,当你开始处理图像.文字.音频和视频数据,你可以使用 Python 的标准库加载数据进入 Num ...

  8. 1.5V转5V的最少电路的芯片电路图

    PW5100满足1.5V转5V的很简洁芯片电路,同时达到了最少的元件即可组成DC-DC电路1.5V转5V的升压转换器系统. PW5100在1.5V转5V输出无负载时,输入效率电流极低,典型值10uA. ...

  9. Centos 7 关机和重启 命令

    1,关机命令 1 shutdown -h now/0 2 halt 3 init 0 4 poweroff 5 举例: 6 shutdown -h 3 ------3分钟后关机(可用shutdown ...

  10. 获取Java线程转储的常用方法

    1. 线程转储简介 线程转储(Thread Dump)就是JVM中所有线程状态信息的一次快照. 线程转储一般使用文本格式, 可以将其保存到文本文件中, 然后人工查看和分析, 或者使用工具/API自动分 ...