题目链接:

http://www.lydsy.com/JudgeOnline/problem.php?id=3240

3240: [Noi2013]矩阵游戏

Time Limit: 10 Sec  Memory Limit: 256 MB

Submit: 317  Solved: 152

[Submit][Status]

Description

婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用操心她怎样存储)。她生成的这个矩阵满足一个奇妙的性质:若用F[i][j]来表示矩阵中第i行第j列的元素。则F[i][j]满足以下的递推式:



F[1][1]=1

F[i,j]=a*F[i][j-1]+b (j!=1)

F[i,1]=c*F[i-1][m]+d (i!=1)

递推式中a,b,c,d都是给定的常数。



如今婷婷想知道F[n][m]的值是多少,请你帮助她。因为终于结果可能非常大,你仅仅须要输出F[n][m]除以1,000,000,007的余数。

Input

一行有六个整数n,m,a,b,c,d。意义如题所述

Output

包括一个整数,表示F[n][m]除以1,000,000,007的余数

Sample Input

3 4 1 3 2 6

Sample Output

85

HINT

例子中的矩阵为:



1 4 7 10



26 29 32 35



76 79 82 85

Source





解题思路:

十进制高速幂

须要优化常数,能够把矩阵优化到仅仅保存两个数。每次矩阵乘法时,仅仅需计算两次乘法即可了。大大加快了速度。

显然最后结果为A^m(BA^mF)^n 当中A(a,b,0,1)  B(c,d,0,1) F(1,0,0,1)

保存一个v1,v2. 矩阵乘法时 c.v1=a.v1*b.v1 c.v2=a.v1*b.v2+a.v2    (ta*(1,2)+tb=(ta*1,ta*2+tb))

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
//#define ll __int64
#define ll long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define MM 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; #define Maxn 1100000 char s1[Maxn],s2[Maxn];
ll a,b,c,d; void sub(char * cur)
{
int len=strlen(cur); len--;
if(cur[len]!='0')
{
cur[len]=cur[len]-1;
return ;
}
cur[len]='9';
len--; while(len>=0&&cur[len]=='0')
{
cur[len]='9';
len--;
}
cur[len]=cur[len]-1;
}
struct Mar
{
ll v1,v2; void init(ll a,ll b)
{
v1=a;
v2=b;
}
friend struct Mar operator * (const struct Mar &a,const struct Mar &b)
{ Mar c; c.v1=(a.v1*b.v1)%MM;
c.v2=(a.v1*b.v2+a.v2)%MM; return c; } }; Mar Pow(Mar aa,ll bb)
{
Mar c;
c.init(1,0);
//c.s[1][1]=1,c.s[2][2]=1; while(bb)
{
if(bb&1)
c=aa*c;
bb>>=1;
aa=aa*aa;
}
return c;
}
Mar T_Pow(Mar aa,char * cur)
{
Mar res;
res.init(1,0); int i=strlen(cur)-1;
int j=0;
while(cur[j]=='0')
j++;
while(i>=j)
{
res=Pow(aa,cur[i]-'0')*res;
aa=Pow(aa,10);
i--;
}
return res;
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout); while(~scanf("%s%s",s1,s2))
{
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
sub(s1);
//printf("%s\n",s1);
sub(s2);
//printf("%s\n",s2);
// ll n=cal(s1),m=cal(s2); Mar A;
A.init(a,b);
//A.s[1][1]=a,A.s[1][2]=b,A.s[2][2]=1;
Mar B;
B.init(c,d);
//B.s[1][1]=c,B.s[1][2]=d,B.s[2][2]=1; Mar C=T_Pow(A,s2);
Mar D=B*C;
D=T_Pow(D,s1);
D=C*D; printf("%lld\n",(D.v1+D.v2)%MM); }
return 0;
}

解题思路:

能够暴力推出公式.费马小定理不适合于矩阵的次幂,a=c=1时,退化成等差数列。需特判,其余等比数列。这题这样做有问题。矩阵的次幂不能用费马小定理来降次,仅仅是这题有点特殊。

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
//#define ll __int64
#define ll long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define MM 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; #define Maxn 1100000 char s1[Maxn],s2[Maxn];
ll a,b,c,d,M; ll cal(char * s)
{
ll res=0;
int i=0; while(s[i])
{
res=(res*10+s[i]-'0')%M;
i++;
}
return (res-1+M)%M; } struct Mar
{
ll s[3][3];
int row,col; void init(int a,int b)
{
row=a,col=b;
memset(s,0,sizeof(s));
} };
struct Mar operator * (const struct Mar &a,const struct Mar &b)
{
Mar c; c.init(a.row,b.col); for(int k=1;k<=a.col;k++)
{
for(int i=1;i<=a.row;i++)
{
if(!a.s[i][k])
continue;
for(int j=1;j<=b.col;j++)
{
if(!b.s[k][j])
continue;
c.s[i][j]=(c.s[i][j]+a.s[i][k]*b.s[k][j])%MM;
}
}
}
return c; } Mar Pow(Mar aa,ll bb)
{
Mar c;
c.init(aa.row,aa.col);
c.s[1][1]=1,c.s[2][2]=1; while(bb)
{
if(bb&1)
c=aa*c;
bb>>=1;
aa=aa*aa;
}
return c;
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout); while(~scanf("%s%s",s1,s2))
{
scanf("%lld%lld%lld%lld",&a,&b,&c,&d); if(a==1&&c==1)
M=MM;
else
M=MM-1;
// M=MM-1;
ll n=cal(s1),m=cal(s2); Mar A;
A.init(2,2);
A.s[1][1]=a,A.s[1][2]=b,A.s[2][2]=1; Mar B;
B.init(2,2);
B.s[1][1]=c,B.s[1][2]=d,B.s[2][2]=1; Mar C=Pow(A,m);
Mar D=B*C;
D=Pow(D,n);
D=C*D; printf("%lld\n",(D.s[1][1]+D.s[1][2])%MM); }
return 0;
}

(十进制高速幂+矩阵优化)BZOJ 3240 3240: [Noi2013]矩阵游戏的更多相关文章

  1. bzoj 3240: [Noi2013]矩阵游戏 矩阵乘法+十进制快速幂+常数优化

    3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 613  Solved: 256[Submit][Status] ...

  2. 高速幂 POW优化

    #include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h&g ...

  3. hdu 5411 CRB and Puzzle 矩阵高速幂

    链接 题解链接:http://www.cygmasot.com/index.php/2015/08/20/hdu_5411/ 给定n个点 常数m 以下n行第i行第一个数字表示i点的出边数.后面给出这些 ...

  4. ZOJ 3690 &amp; HDU 3658 (矩阵高速幂+公式递推)

    ZOJ 3690 题意: 有n个人和m个数和一个k,如今每一个人能够选择一个数.假设相邻的两个人选择同样的数.那么这个数要大于k 求选择方案数. 思路: 打表推了非常久的公式都没推出来什么可行解,好不 ...

  5. $[TJOI2017]$ 可乐 矩阵优化$dp$

    \(Sol\) 设\(f_i\)为到第\(i\)秒的方案数,显然\(f_i=\)在第\(i\)秒前爆炸的方案数+在第\(i\)秒爆炸的方案数+在第\(i\)秒停下的方案数+在第\(i\)秒走向下一个城 ...

  6. bzoj 3240 矩阵乘法+十进制快速幂

    首先,构造出从f[][i]->f[][i+1]的转移矩阵a,和从f[i][m]->f[i+1][1]的转移矩阵b, 那么从f[1][1]转移到f[n][m]就是init*(a^(m-1)* ...

  7. BZOJ 3240 [Noi2013]矩阵游戏 ——费马小定理 快速幂

    发现是一个快速幂,然而过不去. 怎么办呢? 1.十进制快速幂,可以用来练习卡时. 2.费马小定理,如果需要乘方的地方,可以先%(p-1)再计算,其他地方需要%p,所以需要保存两个数. 然后就是分类讨论 ...

  8. BZOJ 3240: [Noi2013]矩阵游戏

    3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1586  Solved: 698[Submit][Status ...

  9. BZOJ 3240([Noi2013]矩阵游戏-费马小定理【矩阵推论】-%*s-快速读入)

    3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec   Memory Limit: 256 MB Submit: 123   Solved: 73 [ Submit][ St ...

随机推荐

  1. Node.js:Buffer

    ylbtech-Node.js:Buffer 1.返回顶部 1. Node.js Buffer(缓冲区) JavaScript 语言自身只有字符串数据类型,没有二进制数据类型. 但在处理像TCP流或文 ...

  2. Codeforces Round #449

    960  asteri 1384     492 00:04 -1 892 01:33     960 PEPElotas 1384     488 00:06 896 00:26       960 ...

  3. Android通过百度地图API用Service和Alarm在后台定时获取地理位置信息

    本文主要介绍了Android项目集成百度地图API,使用AlarmManager定时调用Service,在Service中请求坐标更新,并通过坐标得到省.市和县三级地理位置信息的方法. 程序结构很简单 ...

  4. android黑科技系列——破解游戏之修改金币数

    我们在玩游戏的时候总是会遇到一些东东需要进行购买的,但是我们可能又舍不得花钱,那么我们该怎么办呢?那就是用游戏外挂吧!我们这里说的是Android中的游戏,在网上搜索一下移动端游戏外挂,可能会找到一款 ...

  5. MySQL 5.6 Reference Manual-14.5 InnoDB Tablespace Management

    14.5 InnoDB Tablespace Management   14.5.1 Resizing the InnoDB System Tablespace 14.5.2 Changing the ...

  6. SQLServer 事务的隔离级别

    SQLServer事务的隔离级别 数据库是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况. 更新丢失(Lost update) 两个事务都同时更新一行数据,但是第二个事务 ...

  7. sphinx with discuz

    安装sphinx: sudo apt-get install sphinxsearch 配置: source discuz { type = mysql sql_host = xx.xx.xx.xx ...

  8. 几个书本上不常见到的C语言函数

    函数名称:getcwd #include <unistd.h> char *getcwd(char *buf, size_t size); 作用:把当前目录的绝对地址保存到 buf 中,b ...

  9. /usr/bin/ld: cannot find -lxxx 问题 解决方法总结

    最近在做毕设的收尾工作,很多程序都要部署到linux下来运行,遇到了挺多问题,昨天就集中性遇到了 在编译应用时,遇到了 /usr/bin/ld: cannot find -lxxx 这种情况是系统找不 ...

  10. 从无到有创建一个grunt项目

    在安装好grunt的前提下创建一个grunt的项目: 1.首先创建一个项目文件 就叫grunt-project 2.进入这个文件 创建一个index.html 在创建一个js文件,进去创建一个inde ...