UVa 10870 - Recurrences (矩阵构造 矩阵快速幂)
来源:互联网 发布:生死手游刷金币软件 编辑:程序博客网 时间:2024/06/05 09:06
[Submit] [Go Back] [Status]
Description
Problem A
Recurrences
Input: standard input
Output: standard output
Consider recurrent functions of the following form:
f(n) = a1 f(n - 1) + a2 f(n - 2) + a3 f(n - 3) + ... + ad f(n - d), for n > d.
a1, a2, ..., ad - arbitrary constants.
A famous example is the Fibonacci sequence, defined as: f(1) = 1, f(2) = 1, f(n) = f(n - 1) + f(n - 2). Here d = 2, a1 = 1, a2 = 1.
Every such function is completely described by specifying d (which is called the order of recurrence), values of d coefficients: a1, a2, ..., ad, and values of f(1), f(2), ..., f(d). You'll be given these numbers, and two integers n and m. Your program's job is to compute f(n) modulo m.
Input
Input file contains several test cases. Each test case begins with three integers: d, n, m, followed by two sets of d non-negative integers. The first set contains coefficients: a1, a2, ..., ad. The second set gives values of f(1), f(2), ..., f(d).
You can assume that: 1 <= d <= 15, 1 <= n <= 231 - 1, 1 <= m <= 46340. All numbers in the input will fit in signed 32-bit integer.
Input is terminated by line containing three zeroes instead of d, n, m. Two consecutive test cases are separated by a blank line.
Output
For each test case, print the value of f(n) (mod m) on a separate line. It must be a non-negative integer, less than m.
Sample Input Output for Sample Input
1 1 100
2
1
2 10 100
1 1
1 1
3 2147483647 12345
12345678 0 12345
1 2 3
0 0 0
1
55
423
Problem setter: Max Furlong
Special Thanks: Derek Kisman, EPS.
Source
Root :: Competitive Programming 2: This increases the lower bound of Programming Contests. Again (Steven & Felix Halim) :: Mathematics :: Powers of a (Square) Matrix - Standard
Root :: AOAPC I: Beginning Algorithm Contests -- Training Guide (Rujia Liu) :: Chapter 2. Mathematics :: Matrix & System of Linear Equations :: Examples
[Submit] [Go Back] [Status]
题意:
考虑线性递推关系f(n)=a1*f(n-1) + a2*f(n-2) + .. ad*f(n-d),计算f(n)
n<=2^31-1,如果直接递推肯定超时
第一次接触这种通过矩阵来快速求线性递推式的第n项,一般方式如下
设矩阵Fn = [ f(n) f(n-1) f(n-2) ... f(n-d) ]
然后构造一个矩阵(称为友矩阵或者Q矩阵)A,满足如下:
Fn-1 * A = Fn ==>
[ f(n-1) f(n-2) ... f(n-1-d) ] * A = [ f(n) f(n-1) f(n-2) ... f(n-d) ]
在Fn-1里面f(n-1)..f(n-d)都计算出来了,可以直接用,然后要通过给的条件计算出f(n),
A :
a1 1 0 0 0 0 ...
a2 0 1 0 0 0 ...
a3 0 0 1 0 0 ...
a4 0 0 0 1 0 ...
a5 0 0 0 0 1 ...
....
这个矩阵就是满足条件的矩阵
Fn = Fd * A^(n-d)
A^(n-d)可以通过矩阵快速幂来计算。
所以总的复杂度就是矩阵快速幂的复杂度 O(d^3 * log(n))
#include <cstdio>#include <iostream>#include <vector>#include <algorithm>#include <cstring>#include <string>#include <map>#include <cmath>#include <queue>#include <set>using namespace std;//#define WIN#ifdef WINtypedef __int64 LL;#define iform "%I64d"#define oform "%I64d\n"#define oform1 "%I64d"#elsetypedef long long LL;#define iform "%lld"#define oform "%lld\n"#define oform1 "%lld"#endif#define S64I(a) scanf(iform, &(a))#define P64I(a) printf(oform, (a))#define P64I1(a) printf(oform1, (a))#define REP(i, n) for(int (i)=0; (i)<n; (i)++)#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)const int INF = 0x3f3f3f3f;const double eps = 1e-9;const double PI = (4.0*atan(1.0));const int maxn = 20;struct Matrix { LL e[maxn][maxn]; int n, m; Matrix(int n=0, int m=0) : n(n), m(m) { clear(); } void clear() { memset(e, 0, sizeof(e)); }};Matrix GA;Matrix F;Matrix MatrixMult(Matrix a, Matrix b, int MOD) { Matrix res(a.n, b.m); for(int i=0; i<res.n; i++) { for(int j=0; j<res.m; j++) { for(int k=0; k<a.m; k++) { res.e[i][j] = (res.e[i][j] + a.e[i][k] * b.e[k][j] ) % MOD; } } } return res;}Matrix MatrixPow(Matrix A, int p, int MOD) { Matrix res(A.n, A.m); for(int i=0; i<res.n; i++) res.e[i][i] = 1; while(p) { if(p & 1) res = MatrixMult(res, A, MOD); A = MatrixMult(A, A, MOD); p >>= 1; } return res;}int main() { int d, n, MOD; while(scanf("%d%d%d", &d, &n, &MOD) != EOF && (d || n || MOD)) { GA.clear(); GA.n = GA.m = d; F.n = 1; F.m = d; for(int i=0; i<d; i++) { scanf("%lld", &GA.e[i][0]); } for(int i=1; i<d; i++) { GA.e[i-1][i] = 1; } for(int i=d-1; i>=0; i--) { scanf("%lld", &F.e[0][i]); } if(n <= d) { printf("%lld\n", F.e[0][n-1]); continue; } int p = n - d; GA = MatrixPow(GA, p, MOD); F = MatrixMult(F, GA, MOD); LL ans = F.e[0][0]; printf("%lld\n", ans); } return 0;}
- UVa 10870 - Recurrences (矩阵构造 矩阵快速幂)
- UVA 10870 Recurrences(构造矩阵和快速幂)
- uva 10870 Recurrences(矩阵快速幂)
- UVA - 10870 Recurrences (矩阵快速幂)
- UVA 10870 Recurrences(矩阵快速幂)
- UVA - 10870 Recurrences(构造矩阵)
- UVA 10870 Recurrences 矩阵快速幂
- UVa 10870 Recurrences / 矩阵快速幂
- UVA 10870 - Recurrences(矩阵快速幂)
- uva 10870 - Recurrences(矩阵快速幂)
- UVA - 10870 Recurrences (矩阵快速幂)
- UVA - 10870 Recurrences 矩阵快速幂
- UVa - 10870 - Recurrences ( 矩阵快速幂 )
- UVa 10870 Recurrences (矩阵快速幂)
- 【矩阵快速幂】Recurrences UVA
- Uva 10870 Recurrences 解题报告(矩阵快速幂)
- uva 10870 Recurrences(数学:矩阵快速幂)
- 递推关系( Recurrences, UVa 10870)(矩阵快速幂)
- 不同数据库oracle mysql SQL Server DB2 infomix sybase分页查询语句
- 在Centos中yum安装和卸载软件的使用方法[转]
- 目标检测中背景建模方法
- c++学习笔记--异常处理
- 获取 web界面数据
- UVa 10870 - Recurrences (矩阵构造 矩阵快速幂)
- (入门贴)JVM堆内存相关的启动参数:年轻代、老年代和永久代的内存分配
- 使用 Spring Data JPA 简化 JPA 开发
- Remote_login_passwordfile参数探究
- SQL——基本表的创建和撤销
- JSP应用开发的背景及特点
- windows下cmake的使用
- 使用loadrunner进行压力测试——post请求
- 现在存在瑕疵