Algorithm 矩阵的运算 HDU 1757

Problem Description
Lele now is thinking about a simple function f(x).

If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .

Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.
 

Input
The problem contains mutiple test cases.Please process to the end of file.
In each case, there will be two lines.
In the first line , there are two positive integers k and m. ( k<2*10^9 , m < 10^5 )
In the second line , there are ten integers represent a0 ~ a9.
 

Output
For each case, output f(k) % m in one line.
 

Sample Input
  
  
10 9999 1 1 1 1 1 1 1 1 1 1 20 500 1 0 1 0 1 0 1 0 1 0
 

Sample Output
  
  
45 104 下面我们研究一下这道题如何运用矩阵。

f(x) = a0 *f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10) 构造的矩阵是:

|0 1 0 ........ 0|    |f0|  |f1 | |0 0 1 0 .......0|    |f1|  |f2 | |...............1| |..| =|...| |a9 a8.........a0|    |f9|  |f10|

我们看到规律了,每次要到下次个A*B,以此类推则由A*A*A.......A*B 那么这个问题就转化成了矩阵的幂运算。在上一篇的内容有讲到
<span style="font-size:18px;">#include <iostream>
using namespace std;
#define ll __int64

struct Mat 
{
	int martix[10][10];
};

ll n,m;
Mat init,q,tp,res;

Mat Mul(Mat a,Mat b)
{
	int i,j,k;
	Mat c;
	for(i=0;i<10;i++)
	{
		for(j=0;j<10;j++)
		{
			c.martix[i][j]=0;
			for(k=0;k<10;k++)
			{
				c.martix[i][j]+=(a.martix[i][k]*b.martix[k][j])%m;
				c.martix[i][j]%=m;
			}
		}
	}
	return c;
}

void mat_pow(ll x)  
{
	tp=q;
	q=res;
	while(x)
	{
		if(x&1)
			q=Mul(q,tp);
		tp=Mul(tp,tp);
		x=x>>1;
	}
}

int main()
{
	int i,j,sum;
	memset(init.martix,0,sizeof(init.martix));
	init.martix[1][0]=1;
	init.martix[2][1]=1;
	init.martix[3][2]=1;
	init.martix[4][3]=1;
	init.martix[5][4]=1;
	init.martix[6][5]=1;
	init.martix[7][6]=1;
	init.martix[8][7]=1;
	init.martix[9][8]=1;
	for(i=0;i<10;i++)
	{
		for(j=0;j<10;j++)
		{
			if(i==j)
				res.martix[i][j]=1;
			else
				res.martix[i][j]=0;
		}
	}
	while (scanf("%I64d%I64d",&n,&m)!=EOF)
	{
		q=init;
		for(i=0;i<10;i++)
			scanf("%d",&q.martix[0][i]);
		if(n>=10)
		{
			sum=0;
			mat_pow(n-9);
			for(i=0;i<10;i++)
				sum+=q.martix[0][i]*(9-i);
			printf("%d/n",sum%m);
		}
		else
			printf("%d/n",n%m);
		
	}
	return 0;
}</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值