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