Simple Math Problem HDU - 1757 (矩阵快速幂)

Simple Math Problem

题目链接:HDU - 1757

题意:定义了一个函数: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);

递推式已经有了,再找转移矩阵f(0)~f(9)分别是0, 1, 2, 3, 4, 5, 6, 7, 8, 9;

10*10的矩阵;

#include 
using namespace std;
const int M=15;
long long k, m;
long long a[M];
long long t[M][M], f[]={9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
void mul(long long x[][M], long long y[][M]){
	long long temp[15][15];
	memset(temp, 0, sizeof(temp));
	for(int i=0; i<10; i++){
		for(int j=0; j<10; j++){
			for(int k=0; k<10; k++){
				temp[i][j]=(temp[i][j]+x[i][k]*y[k][j]%m)%m;
			}
		}
	}
	for(int i=0; i<10; i++){
		for(int j=0; j<10; j++){
			x[i][j]=temp[i][j];
		}
	}
	return;
}
long long Power(long long x[][15], long long n){
	long long temp[15][15];
	for(int i=0; i<10; i++){
		for(int j=0; j<10; j++){
			temp[i][j]=(i==j?1:0);
		}
	}
	while(n){
		if(n&1) mul(temp, x);
		mul(x, x);
		n>>=1;
	}
	long long ans=0;
	for(int i=0; i<10; i++){
		ans=(ans+temp[0][i]*f[i]%m)%m;
	}
	return ans;
}
int main(){
	while(~scanf("%lld%lld", &k, &m)){
		memset(t, 0, sizeof(t));
		for(int i=0; i<10; i++){
			scanf("%lld", &a[i]);
			t[0][i]=a[i];
		}
		for(int i=1; i<10; i++){
			t[i][i-1]=1;
		}
		if(k<10) printf("%lld\n", k%m);
		else{
			printf("%lld\n", Power(t, k-9));	
		}
	}
	return 0;
}

你可能感兴趣的:(快速幂)