题目链接:http://acm.hust.edu.cn/vjudge/problem/28800
题意:f(n) = a1f(n − 1) + a2f(n − 2) + a3f(n − 3) + . . . + adf(n − d), for n > d,
给出a1~ad,f1~fd,求f(n)。
思路:一个简单的矩阵快速幂,设定好转移矩阵直接乘即可。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;
#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)
#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod 100000007
const int maxn = 15;
int n,d,m;
int A[maxn];
int F[maxn];
struct node
{
int a[maxn][maxn];
void E()
{
Clean(a,0);
rep(i,0,maxn-1)
a[i][i] = 1;
}
void P(int n)
{
Clean(a,0);
rep(i,1,n-1) a[i][i-1] = 1;
rep(i,0,n-1) a[i][n-1] = A[ n-1-i ];
}
};
node multi( node &x , node &y , int z )
{
node ans;
rep(i,0,z-1)
rep(j,0,z-1)
{
ans.a[i][j] = 0;
rep(k,0,z-1)
ans.a[i][j] = ( ans.a[i][j] + x.a[i][k] * y.a[k][j] ) % m;
}
return ans;
}
int main()
{
while( ~scanf("%d%d%d",&d,&n,&m) )
{
if ( n == 0 && d == 0 && m == 0 ) break;
rep(i,0,d-1) scanf("%d",&A[i]);
rep(i,0,d-1) scanf("%d",&F[i]);
rep(i,0,d-1)
{
A[i] %= m;
F[i] %= m;
}
if ( n <= d )
printf("%d\n",F[n-1]%m);
else
{
n--;
node ans,temp;
ans.E();
temp.P(d);
while( n )
{
if ( n & 1 ) ans = multi( ans , temp , d );
temp = multi( temp , temp , d );
n >>= 1;
}
int S = 0;
rep(i,0,d-1)
S = ( S + F[i] * ans.a[i][0] ) % m;
printf("%d\n",S);
}
}
return 0;
}