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)*b)^(n-1)*(a^(m-1))。

然后用用十进制快速幂(因为输入用的是10进制,这样就避免了高精度除法)。

第一次写十进制快速幂,大概的思想是维护当前位是1~9的要乘的矩阵,然后再通过这9个矩阵自己转移。

 1 /**************************************************************
 2     Problem: 3240
 3     User: idy002
 4     Language: C++
 5     Result: Accepted
 6     Time:5352 ms
 7     Memory:2764 kb
 8 ****************************************************************/
 9
10 #include <cstdio>
11 #include <cstring>
12 #include <cctype>
13 #include <algorithm>
14 #define N 1000010
15 #define Mod 1000000007
16 using namespace std;
17
18 typedef long long dnt;
19 struct Matrix {
20     dnt v[2][2];
21     void make_unit() {
22         for( int i=0; i<2; i++ )
23             for( int j=0; j<2; j++ )
24                 v[i][j] = (i==j);
25     }
26     inline const dnt* operator[]( int i ) const { return v[i]; }
27     Matrix(){}
28     Matrix( int aa, int ab, int ba, int bb ) {
29         v[0][0] = aa, v[0][1] = ab, v[1][0] = ba, v[1][1] = bb;
30     }
31     Matrix operator*( const Matrix &b ) const {
32         const Matrix &a = *this;
33         return Matrix( 1, (b[0][1]+a[0][1]*b[1][1])%Mod,
34                        0, a[1][1]*b[1][1]%Mod );
35     }
36     Matrix operator^( const char *b ) const {
37         Matrix rt, q[10];
38
39         q[1] = *this;
40         for( int i=2; i<=9; i++ )
41             q[i] = q[i-1]*q[1];
42
43         rt.make_unit();
44         for( int i=0; b[i]; i++ ) {
45             if( b[i]-‘0‘ ) rt = rt*q[b[i]-‘0‘];
46             q[1] = q[1]*q[9];
47             for( int j=2; j<=9; j++ )
48                 q[j] = q[j-1]*q[1];
49         }
50         return rt;
51     }
52 };
53
54 char sn[N], sm[N];
55 int ln, lm;
56 int a, b, c, d;
57 Matrix ma, mb, ans;
58
59 void subone( char s[] ) {
60     int i = 0;
61     s[i]--;
62     while( s[i]<‘0‘ ) {
63         s[i] += 10;
64         s[i+1]--;
65         i++;
66     }
67 }
68 int main() {
69     scanf( "%s%s%d%d%d%d", sn, sm, &a, &b, &c, &d );
70     ln = strlen(sn), lm = strlen(sm);
71     reverse( sn, sn+ln );
72     reverse( sm, sm+lm );
73     subone(sn), subone(sm);
74     ma = Matrix(1,b,0,a)^sm;
75     mb = Matrix(1,d,0,c);
76     ans = ((ma*mb)^sn)*ma;
77     printf( "%lld\n", (ans[0][1]+ans[1][1]) % Mod );
78 }

时间: 2024-10-07 12:44:38

bzoj 3240 矩阵乘法+十进制快速幂的相关文章

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

3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 613  Solved: 256[Submit][Status] Description 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式: F[1][1]=1F[i,j]=a*F[i][j-1]+

矩阵乘法、快速幂

1 #include <cstdio> 2 #include <iostream> 3 #include <vector> 4 #include <cstring> 5 using namespace std; 6 // 矩阵的STL实现 7 typedef vector<int> vec; 8 typedef vector<vec> mat; 9 typedef long long ll; 10 const int MOD = 10

poj3613:Cow Relays(倍增优化+矩阵乘法floyd+快速幂)

Cow Relays Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7825   Accepted: 3068 Description For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race using the T (2 ≤ T ≤ 100) cow trails throughout

BZOJ_1009_[HNOI2008]_GT考试_(动态规划+kmp+矩阵乘法优化+快速幂)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1009 字符串全部由0~9组成,给出一个串s,求一个长度为n的串,不包含s的种类有多少. 分析 第一眼以为是组合.然后更滑稽的是用错误的方法手算样例居然算出来是对的...我数学是有多差... 题解也是看了好半天,有点难理解. 感觉PoPoQQQ神犇讲得还是比较清楚的.传送门:http://blog.csdn.net/popoqqq/article/details/40188173 我们用dp[

【HDOJ5950】Recursive sequence(矩阵乘法,快速幂)

题意:f[1]=a,f[2]=b,f[i]=2f[i-2]+f[i-1]+i^4(i>=3),多组询问求f[n]对2147493647取模 N,a,b < 2^31 思路:重点在于i^4的处理 对于i转移矩阵中可以记录下它的0,1,2,3,4次项 i的幂又可以由i-1的幂运算得出,最后推出的系数是二项式展开的系数 试试新的矩乘模板 1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #inc

10.02 T3 打表找递推式+十进制快速幂 九校联考凉心模拟DAY1T1

题目背景 金企鹅同学非常擅长用1*2的多米诺骨牌覆盖棋盘的题.有一天,正 在背四六级单词的他忽然想:既然两个格子的积木叫“多米诺(domino)”,那 么三个格子的的积木一定叫“三米诺(tromino)”了!用三米诺覆盖棋盘的题 怎么做呢? 题目描述 用三米诺覆盖3n 的矩形棋盘,共多少种方案?三米诺可旋转:两种 方案不同当且仅当这两种图案直接覆盖在一起无法重叠. 输入输出格式 输入格式: 一行一个整数n(n<=10^40000),表示棋盘列数. 输出格式: 一行一个整数,表示方案数,对9982

快速乘法(基于快速幂)

快速乘法的思想和快速幂的思想一样,快速幂是求一个数的高次幂,快速乘法是求两个数相乘,什么时候才用得到快速乘法呢,当两个数相称可能超过long long 范围的时候用,因为在加法运算的时候不会超,而且可以直接取模,这样就会保证数据超不了了.具体拿一个BestCoder的题目来示例.题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5187 这个题先找规律,然后在求快速乘法和快速幂结合起来.题目推出来通式是:2n-2 推的过程就是一共有四种情况: 升升,升

BZOJ 1008 越狱 题解 裸快速幂

BZOJ 1008 越狱 题解 裸快速幂 1008: [HNOI2008]越狱 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 7887  Solved: 3372[Submit][Status][Discuss] Description 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱 Input 输入两个整数M,N.1<=M<

模板—十进制快速幂

用于指数爆longlong的情况,当然你也可以打高精…… 因为昨天有人提到了慢速乘,感觉挺有用的,就顺便都学了吧,而且省选也用到十进制快速幂了. #include<iostream> #include<cstring> #include<cstdio> #define LL long long using namespace std; char c[100000]; LL a,p,t; LL tenthpow(LL a) { LL ans=1,s=a; while(t&