矩阵快速幂3(Experienced Endeavour, 233 Matrix, So Easy!, Construct a Matrix)

目录

Experienced Endeavour

233 Matrix

So Easy!

Construct a Matrix


 

 


问题7:

Experienced Endeavour

UVA - 11551

Alice is given a list of integers by Bob and is asked to generate a new list where each element in the new list is the sum of some other integers in the original list. The task is slightly more involved, as Bob also asks Alice to repeat this several times before giving him the result. Help Alice automate her task.
Input

The first line of the input is t (1 ≤ t ≤ 10), the number of cases to follow. Each case is in the following format:
n r

a0 a1 ... an−1

x0 b0,0 b0,1 ... b0,x0−1

x1 b1,0 b1,1 ... b1,x1−1 . . .

xn−1 bn−1,0 bn−1,1 ... bn−1,xn−1−1

Each case begins with the integer n (1 ≤ n ≤ 50), which is the number of elements in the list of integers that Alice is given. The integer r (1 ≤ r ≤ 109) is the number of times these operations are to be repeated on a list before returning the result. The values are the nonnegative integers in the original list. Then n lines follow that define how Alice will generate a new list from a previous one. Each of these lines are in the form:
xi bi,0 bi,1 ... b1,xi

This line defines the value of the i-th element in the new list to be the sum of elements:

abi,0,abi,1,...,ab1,xi−1


Output
The output consists of t lines, one line for each test case listing the final list of integers modulo 1000 in the form:

c0 c1 ... cn−1


Sample Input
2

2 2

1 2

2 0 1

1 1

2 4

507 692

2 0 1

1 1

Sample Output
5 2

275 692


题意:This line defines the value of the i-th element in the new list to be the sum of elements: abi,0,abi,1,...,ab1,xi−1。给出a1,a2,a3,······,再给出对应下标0,1,2,3,···,把这些下标对应的a1,a2,···加起来构成新的a,反复r次后输出新的a。

思路:建一个n×n的矩阵,将出现过的下标对应位置记为1,其他位置记为0,以题中情况一为例:

代码:

#include<iostream>
#include<cstring>
#include<vector>
#include<cmath>

using namespace std;
typedef long long ll;
struct matrix
{
	ll mat[50][50];
	matrix() {
		memset(mat, 0, sizeof(mat));
	}
}U, F;
ll mod=1000;
matrix mul(matrix Q, matrix A)
{
	matrix C;
	for (int i = 0; i < 50; i++)
		for (int j = 0; j < 50; j++)
			for (int k = 0; k < 50; k++)
				C.mat[i][j] = (C.mat[i][j] + A.mat[i][k] * Q.mat[k][j]) % mod;
	return C;
}
matrix powmul(matrix A, int m)
{
	matrix ans = F;
	while (m > 0)
	{
		if (m & 1)
			ans = mul(ans, A);
		A = mul(A, A);
		m >>= 1;
	}
	return ans;
}
int main() {
	int N; cin >> N;
	while (N--)
	{
		ll n, r;
		matrix ans;
		cin >> n >> r;
		for (int i = 0; i < n; i++)
			cin >> F.mat[i][0]; //输入a1,a2,a3···
		int num = 0;
		for (int i = 0; i < n; i++) 
		{
			cin >> num;
			for (int j = 0; j < num; j++)
			{
				int k; cin >> k;
				U.mat[i][k] = 1; //出现过的下标在转移矩阵中都设为1
			}
		}
	    ans = powmul(U, r);
		for (int i = 0; i < n; i++) {
			cout << ans.mat[i][0];
			if (i < n - 1)
				cout << " "; //输出格式要注意
		}
		cout << endl;
		for (int i = 0; i < n; i++)         //转移矩阵记得清零!
			for (int j = 0; j < n; j++)
				U.mat[i][j] = 0;
	}
	return 0;
}

问题八:

233 Matrix

HDU - 5015

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

 


题意:给出n,m,再给出a1到an的值,它们在矩阵的第零列。根据计算规则 a i,j = a i-1,j +a i,j-1( i,j ≠ 0),求出a_{n\,m}的值并输出。

分析:现在我们假设要求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] = ...

就等于求A[a][b]左边那一列的数的和加上它正上方第1行的数

   ******** 
  ********  
  ********  
  ********  
  ********A[a][b] 

    矩阵:

               

以第零列为起始列依次推出后面列的值,转移矩阵中的10和3用于计算新的233···值,被1填充的时an m左边那一列(即m-1列)所需加上的数。

 

 

代码:

#include<iostream>
#include<cstring>
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)
{
	matrix C;
	for (int i = 1; i <= n + 2; i++)
		for (int j = 1; j <= n + 2; j++)
			for (int 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() {
	int m;
	while (cin >> n >> m)
	{
		matrix A, B;
		A.mat[1][1] = 23;
		for (int i = 2; i <= n + 1; i++)
			cin >> A.mat[i][1];
		A.mat[n + 2][1] = 3;
		for (int i = 1; i <= n + 2; i++)
		{
			B.mat[i][1] = 10;
			B.mat[i][n + 2] = 1;
		}
		B.mat[n + 2][1] = 0;
		for (int i = 2; i < n + 2; i++)
			for (int j = 2; j <= i; j++)
				B.mat[i][j] = 1;
		B = powmul(B, m);

		A=mul(B, A);
		cout << A.mat[n + 1][1] << endl;
	}
	return 0;
}

问题九:

So Easy!

HDU - 4565

A sequence S n is defined as:


Where a, b, n, m are positive integers.┌x┐is the ceil of x. For example, ┌3.14┐=4. You are to calculate S n.
  You, a top coder, say: So easy!

Input

  There are several test cases, each test case in one line contains four positive integers: a, b, n, m. Where 0< a, m < 2 15, (a-1) 2< b < a 2, 0 < b, n < 2 31.The input will finish with the end of file.

Output

  For each the case, output an integer S n.

Sample Input

2 3 1 2013
2 3 2 2013
2 2 1 2013

Sample Output

4
14
4

题意:给出a,b,n,m根据公式计算Sn;

分析:

代码:

#include<iostream>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
struct matrix
{
	ll mat[2][2];
	matrix() {
		memset(mat, 0, sizeof(mat));
	}
}U, F;
ll mod;
matrix mul(matrix Q, matrix A)
{
	matrix C;
	for (int i = 0; i < 2; i++)
		for (int j = 0; j < 2; j++)
			for (int k = 0; k < 2; k++)
				C.mat[i][j] = ((C.mat[i][j] + A.mat[i][k] * Q.mat[k][j]) % mod+mod)%mod;
	return C;
}
matrix powmul(matrix A, ll m)
{
	matrix ans = F;
	while (m > 0)
	{
		if (m & 1)
			ans = mul(ans, A);
		A = mul(A, A);
		m >>= 1;
	}
	return ans;
}
int main() {
		ll n, a, b;
		while (cin >> a >> b >> n >> mod) 
		{
			if (n == 0)
				cout << 1 << endl;
			else if (n == 1)
				cout <<(2 * a) %mod<< endl;
			else 
			{
				U.mat[0][0] = 2 * a;
				U.mat[0][1] = b - a * a;
				U.mat[1][0] = 1;
				U.mat[1][1] = 0;
				F.mat[0][0] = 2 * a;
				F.mat[0][1] = 0;
				F.mat[1][0] = 2;
				F.mat[1][1] = 0;
				matrix ans = powmul(U, n);
				cout << ans.mat[1][0] << endl;
			}
		}
	return 0;
}

问题十:

Construct a Matrix

FZU - 1911

There is a set of matrixes that are constructed subject to the following constraints:

1. The matrix is a S(n)×S(n) matrix;

2. S(n) is the sum of the first n Fibonacci numbers modulus m, that is S(n) = (F1 + F2 + … + Fn) % m;

3. The matrix contains only three kinds of integers ‘0’, ‘1’ or ‘-1’;

4. The sum of each row and each column in the matrix are all different.

Here, the Fibonacci numbers are the numbers in the following sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …

By definition, the first two Fibonacci numbers are 1 and 1, and each remaining number is the sum of the previous two.

In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation Fn = Fn-1 + Fn-2, with seed values F1 = F2 = 1.

Given two integers n and m, your task is to construct the matrix.

Input

The first line of the input contains an integer T (T <= 25), indicating the number of cases. Each case begins with a line containing two integers n and m (2 <= n <= 1,000,000,000, 2 <= m <= 200).

Output

For each test case, print a line containing the test case number (beginning with 1) and whether we could construct the matrix. If we could construct the matrix, please output “Yes”, otherwise output “No” instead. If there are multiple solutions, any one is accepted and then output the S(n)×S(n) matrix, separate each integer with an blank space (as the format in sample).

Sample Input

2
2 3
5 2

Sample Output

Case 1: Yes
-1 1
0 1
Case 2: No

题意:Sn时斐波那契数列前n项的和,构造Sn×Sn的矩阵,矩阵里的元素只能由0,-1,1构成,要求每行每列的和都不同。

分析:我们要解决两个问题;1.怎么写矩阵方程计算斐波那契数列前n项和?2.怎样构造矩阵才能使每行每列的和都不同?

以前求Fn的时候是二维矩阵,现在要求它们的和,我们要多开一个维度用来计算和。

矩阵: 

Sn×Sn矩阵构造:

如果S[n]是奇数或者0,显然无解。

偶数的话,可以构造答案,下面以6*6为例:

右上部分全是1,左下部分全是-1,对角线部分-1和0交错填充:

代码:

#include<iostream>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
struct matrix
{
	ll mat[3][3];
	matrix() {
		memset(mat, 0, sizeof(mat));
	}
}U, F;
ll mod;
matrix mul(matrix Q, matrix A)
{
	matrix C;
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			for (int k = 0; k < 3; k++)
				C.mat[i][j] = (C.mat[i][j] + (A.mat[i][k] * Q.mat[k][j])%mod) % mod;
	return C;
}
matrix powmul(matrix A, int m)
{
	matrix ans = F;
	while (m > 0)
	{
		if (m & 1)
			ans = mul(ans, A);
		A = mul(A, A);
		m >>= 1;
	}
	return ans;
}
int main() {
	int N,num=0; cin >> N;
	ll n;
	while (N--)
	{
		cin >> n >> mod;
		if (n == 1)
			cout << "Case " << ++num << ": No" << endl;
		else
		{
			F.mat[0][0] = 1; F.mat[1][0] = 1; F.mat[2][0] = 2;

			U.mat[0][0] = 1; U.mat[0][1] = 1; U.mat[1][0] = 1;
			U.mat[2][0] = 1; U.mat[2][1] = 1; U.mat[2][2] = 1;
			matrix ans = powmul(U, n - 2);
			ll Sn = ans.mat[2][0] % mod;
			if (Sn == 0 || Sn & 1)
				cout << "Case " << ++num << ": No" << endl;
			else
			{
				cout << "Case " << ++num << ": Yes" << endl;
				for (int i = 0; i < Sn; i++) {
					for (int j = 0; j < Sn; j++) {
						if (i > j)
							cout << "-1 ";
						if (i < j)
							cout << "1 ";
						if (i == j && i % 2 == 0)
							cout << "-1 ";
						if (i == j && i % 2 == 1)
							cout << "0 ";
					}
					cout << endl;
				}
			}
		}
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值