https://hihocoder.com/contest/offers70/problem/4
POINT:
就是一道比较简单的构造矩阵的问题。
然后用矩阵快速幂来算答案。
思路是把一个1*n的矩阵{a1,a2,a3,a4,an} 右乘一个n*n的矩阵 变为{a2,a3,a4,,a5,an+1}。
构造这个矩阵就很简单了。
这题在赛中数据有错,睡了一觉上去看AC了。应该重判了。也只能在那么水的比赛上拿个第一名了。
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <string>
using namespace std;
#define LL long long
const LL maxn = 22;
const LL mod = 1e9+9;
LL a[22];
LL n;
struct node
{
LL a[maxn][maxn];
void init(){
memset(a,0,sizeof a);
}
node friend operator * (node a,node b)
{
node c;
c.init();
for(LL i=1;i<=n;i++){
for(LL j=1;j<=n;j++){
for(LL k=1;k<=n;k++){
c.a[i][j]+=a.a[i][k]*b.a[k][j];
c.a[i][j]%=mod;
}
}
}
return c;
}
};
int main()
{
LL m,c;
scanf("%lld%lld%lld",&n,&m,&c);
for(LL i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
node b;
b.init();
for(LL i=1;i<n;i++){
b.a[i+1][i]=1;
}
for(LL i=1;i<=c;i++){
LL x;scanf("%lld",&x);
b.a[n+1-x][n]++;
}
if(m<=n){
printf("%lld\n",a[m]);
}else{
node ans;
ans.init();
for(LL i=1;i<=n;i++) ans.a[i][i]=1;
m-=n;
while(m){
if(m&1) ans=ans*b;
b=b*b;
m>>=1;
}
LL z=0;
for(LL i=1;i<=n;i++){
z+=a[i]*ans.a[i][n];
z%=mod;
}
printf("%lld\n",z);
}
}