【hdu5015】233 Matrix——矩阵快速幂

题目:

233 Matrix

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1588    Accepted Submission(s): 939


Problem Description
In our daily life we often use 233 to express our feelings. Actually, we may say 2333, 23333, or 233333 ... in the same meaning. And here is the question: Suppose we have a matrix called 233 matrix. In the first line, it would be 233, 2333, 23333... (it means a 0,1 = 233,a 0,2 = 2333,a 0,3 = 23333...) Besides, in 233 matrix, we got a i,j = a i-1,j +a i,j-1( i,j ≠ 0). Now you have known a 1,0,a 2,0,...,a n,0, could you tell me a n,m in the 233 matrix?
 

Input
There are multiple test cases. Please process till EOF.

For each case, the first line contains two postive integers n,m(n ≤ 10,m ≤ 10 9). The second line contains n integers, a 1,0,a 2,0,...,a n,0(0 ≤ a i,0 < 2 31).
 

Output
For each case, output a n,m mod 10000007.
 

Sample Input
  
  
1 1 1 2 2 0 0 3 7 23 47 16
 

Sample Output
  
  
234 2799 72937
Hint
 

Source
 

Recommend
hujie   |   We have carefully selected several similar problems for you:   5634  5633  5632  5631  5630 
描述:给定233矩阵第0行是2333每次多一个3,给出矩阵元素的递推关系是一个广义的杨辉三角,给定第0列元素以及有n行m列,求a(n,m)

题解:一看到m特别大,就不要想用正常的杨辉三角去一步步推,一定是需要矩阵快速幂去加速运算过程,那么问题来了,这个矩阵如何来找到。首先可以看出,这个矩阵是可以按列进行转移的,第一行都可以看作是前一个*10+3,那么构造新的矩阵的第一列就全是10(转移矩阵左乘列矩阵),然后在列矩阵最后一位加上一个3,将第0列的0元素改为23,这样第一列也满足了这样的规律。接下来看最后一行,由于我们多了一个3,而每次转移都要保持它,所以转移矩阵的最后一列就都是1;然后再分析原矩阵的构造过程,可以看出从第一行开始,每个元素都等于它的前缀(前面所有元素)和,因此转移矩阵在第i行就有i个1.这样转移矩阵就构造结束了。

http://blog.csdn.net/rowanhaoa/article/details/39343769  这里有带图的解释,更直观一些。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct matrix
{
	__int64 mat[15][15];

	matrix()
	{
		memset(mat, 0, sizeof(mat));
	}
};
int n;
const int mod = 10000007;
matrix mul(matrix B, matrix A)         //左乘列矩阵
{
	int i, j, k;
	matrix C;
	for (i = 1; i <= n + 2; i++)
		for (j = 1; j <= n + 2; j++)
			for (k = 1; k <= n + 2; k++)
				C.mat[i][j] = (C.mat[i][j]+B.mat[i][k] * A.mat[k][j])%mod;
	return C;
}
matrix powmul(matrix A, int m)
{
	matrix ans;
	for (int i = 1; i <= n + 2; i++)
		ans.mat[i][i] = 1;              //单位矩阵
	while (m > 0)
	{
		if (m & 1)
			ans = mul(ans, A);
		A = mul(A, A);
		m >>= 1;
	}
	return ans;
}
int main()
{
	//freopen("input.txt", "r", stdin);
	int m;
	while (scanf("%d%d",&n,&m) != EOF)
	{
		matrix A, B;
		A.mat[1][1] = 23;                //原矩阵首元素为23,使每一列都可以被转换(原来第二列不行
		for (int i = 1; i <= n; i++)
			scanf("%d", &A.mat[i + 1][1]);
		A.mat[n + 2][1] = 3;

		for (int i = 1; i <= n + 1; i++)
			B.mat[i][1] = 10;
		for (int i = 1; i <= n + 2; i++)
			B.mat[i][n + 2] = 1;
		for (int i = 1; i < n + 2; i++)
			for (int j = 2; j <= i; j++)
				B.mat[i][j] = 1;     //转移矩阵的下三角单位阵

		B = powmul(B, m);
		A = mul(B, A);               //A除了第一列之外所有的元素都是0,相当于列矩阵

		cout << A.mat[n + 1][1] << endl;
	}

	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值