其他分享
首页 > 其他分享> > QDUOJ 你猜锋锋让不让你过(矩阵快速幂)

QDUOJ 你猜锋锋让不让你过(矩阵快速幂)

作者:互联网

Description
已知
(题目中所提均为整数)
若 x<10 f(x) = x.
若 x>=10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10)
ai(0<=i<=9) 等于0或1
求 f(k)%m

Input
多组样例,k<=2e9 , m<=1e5
每组样例给定输入如下:
第一行两个整数 k m
下面一行是数组a的10个数,从a0到a9

Output
每组样例输出一个整数代表f(k)%m

Sample Input 1
10 9
1 1 1 1 1 0 0 0 0 0
20 18
0 0 0 0 0 1 1 1 1 1

Sample Output 1
8
10

在这里插入图片描述

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;
typedef struct{
	ll mat[15][15];
}Matrix;
Matrix ans, res;
ll k, m;

Matrix mul(Matrix a, Matrix b)
{
	Matrix c;
	memset(c.mat, 0, sizeof(c.mat));
	for (int i=0; i<10; i++){
		for (int j=0; j<10; j++){
			for (int k=0; k<10; k++)
				c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%m;
		}
	}
	return c;
}
ll quick_pow_mod(ll n)
{
	while(n){
		if (n&1)
			ans=mul(res, ans);
	//因为是如果n末尾为1,相乘后的结果又存回了ans;所以不需要单位阵处理n一开始末尾不是1的情况。
		res=mul(res, res);
		n>>=1;
	}
	return ans.mat[0][0]%m;
}
int main()
{
	memset(ans.mat, 0, sizeof(ans.mat));
	
	while(scanf("%lld %lld", &k, &m)!=EOF){
//		if (k<10){
//			printf("%lld\n", k%m);
//			continue;
//		}这样会RE,因为如果conintue了,后面的输入就进不去了 
		
		for (int i=0; i<10; i++)
			ans.mat[i][0]=9-i;
		memset(res.mat, 0, sizeof(res.mat));
		for (int j=0; j<10; j++){
			scanf("%lld", &res.mat[0][j]);
		}
		for (int i=1; i<10; i++)
			res.mat[i][i-1]=1;
		
		
		if(k<10)
	   		printf("%lld\n",k%m);
	   	else
	   		printf("%lld\n",quick_pow_mod(k-9));
	} 
	return 0;
}

标签:10,mat,ll,矩阵,QDUOJ,猜锋锋,ans,include,Matrix
来源: https://blog.csdn.net/weixin_42172261/article/details/94048102