题目链接:https://vjudge.net/problem/HDU-1757
题意:就是求一个函数f(x)的值,如果x<10,f(x)=x,如果f(x)>=10,给你a0~a9一共10个数,f(x)=a0*f(x-1)+a1*f(x-2)+...+f(x-10)*a9。输出结果要对m取模。(k<=2e9,m<=1e5)。
分析:看起来像是个递推,但是看数据范围十分的大,直接抵退肯定超时,构造矩阵,利用矩阵快速幂求解才能提高效率。具体矩阵构造(在网上找的,因为自己懒得画图):
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
const int maxn=10;
int arr[maxn],f[maxn];
int k,MOD;
struct Matrix{
LL mat[maxn][maxn];
Matrix operator*(const Matrix& m) const{//重载乘法运算符
Matrix tmp;
for(int i=0;i<maxn;i++){
for(int j=0;j<maxn;j++){
tmp.mat[i][j]=0;
for(int k=0;k<maxn;k++){
tmp.mat[i][j]+=mat[i][k]*m.mat[k][j]%MOD;
tmp.mat[i][j]%=MOD;
}
}
}
return tmp;
}
};
void init(Matrix& m){ //初始化
memset(m.mat , 0 , sizeof(m.mat));
for(int i=0;i<maxn;i++)
m.mat[0][i]=arr[i];
for(int i=0;i<maxn-1;i++)
m.mat[i+1][i]=1;
for(int i=0;i<maxn;i++)
f[i]=i;
}
LL Pow(Matrix& m){
Matrix ans;
memset(ans.mat,0,sizeof(ans.mat));
for(int i=0;i<maxn;i++)
ans.mat[i][i]=1;
k-=9;
while(k){ //快速幂
if(k&1) ans=ans*m;
k>>=1;
m=m*m;
}
LL sum=0;
for(int i=0;i<maxn;i++){ //计算结果
sum+=ans.mat[0][i]*f[maxn-1-i]%MOD;
sum%=MOD;
}
return sum;
}
int main() {
//freopen("in.txt","r",stdin);
Matrix m;
while(~scanf("%d%d",&k,&MOD)){
for(int i=0;i<maxn;i++)
scanf("%d",&arr[i]);
init(m);
if(k<10) printf("%d\n",k%MOD);
else printf("%lld\n",Pow(m));
}
return 0;
}