HDU 5015 矩阵快速幂

题意:给出矩阵的第0行(233,2333,23333,...)和第0列a1,a2,...an(n<=10,m<=10^9),给出式子: A[i][j] = A[i-1][j] + A[i][j-1],要求A[n][m]。

解法:看到n<=10和m<=10^9 应该对矩阵有些想法,现在我们假设要求A[a][b],则A[a][b] = A[a][b-1] + A[a-1][b] = A[a][b-1] + A[a-1][b-1] + A[a-2][b] = ...

这样相当于右图:,红色部分为绿色部分之和,而顶上的绿色部分很好求,左边的绿色部分(最多10个)其实就是:A[1][m-1],A[2][m-1]..A[n][m-1],即对每个1<=i<=n, A[i][m]都可由A[1][m-1],A[2][m-1]..A[n][m-1],于是建立12*12的矩阵:

,将中间矩阵求m-1次幂,与右边[A[0][1],A[1][1]..A[n][1],3]^T相乘,结果就可以得出了。

题解是转的别人的:http://www.cnblogs.com/whatbeg/p/3971994.html

#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e7 + 7;
struct Matrix
{
	int mat[15][15];
	int n;
	void init(int nn)
	{
		n = nn;
		memset(mat, 0, sizeof(mat));
	}
	Matrix operator*(const Matrix &b) const
	{
		Matrix ret; ret.init(n);
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
			{
				ret.mat[i][j] = 0;
				for (int k = 0; k < n; k++)
				{
					ret.mat[i][j] += (long long)mat[i][k] * b.mat[k][j] % MOD;
					if (ret.mat[i][j] >= MOD)
						ret.mat[i][j] -= MOD;
				}
			}
		return ret;
	}
	Matrix operator^(long long nn)
	{
		Matrix tmp = *this, ret; ret.init(this->n);
		for (int i = 0; i < this->n; i++)
			ret.mat[i][i] = 1;
		while (nn)
		{
			if (nn & 1)ret = ret * tmp;
			tmp = tmp * tmp;
			nn >>= 1;
		}
		return *this = ret;
	}
	void print()
	{
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
			{
				cout << mat[i][j] << (j == n - 1 ? "\n" : " ");
			}
	}
};
int inp[20], n, m;
Matrix A;
int main(int argc, char const *argv[])
{
	ios::sync_with_stdio(false);
	while (cin >> n >> m)
	{
		for (int i = 0; i < n; i++)
		{
			cin >> inp[i];
			inp[i] %= MOD;
		}
		A.init(n + 2);
		for (int j = 0; j < n; A.mat[n][j] = 1, j++)
			for (int i = 0; i <= j; i++)
				A.mat[i][j] = 1;
		A.mat[n][n] = 10; A.mat[n + 1][n] = 3; A.mat[n + 1][n + 1] = 1;
		//A.print();
		A^m;
		//A.print();
		long long ans = 0;
		for (int i = 0; i < n; i++)
		{
			ans += (long long)inp[i] * A.mat[i][n - 1] % MOD;
			ans % MOD;
		}
		ans += (long long)233 * A.mat[n][n - 1];
		ans %= MOD;
		ans += (long long)A.mat[n + 1][n - 1];
		ans %= MOD;
		cout << ans << endl;
	}
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值