题目链接:戳我
题目大意:
一个函数 f(x) 当 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);
给 k 和 m,求 f(k) % m的值
样例解释:
略
解题思路:
用矩阵快速幂,建立A 矩阵为 10 * 10的,如下
0 1 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 1
a[9] a[8] a[7] a[6] a[5] a[4] a[3] a[2] a[1] a[0] 其中a数组为上面公式所对应的a
B矩阵为 10 * 1 的, 如下
[0;1;2;3;4;5;6;7;8;9]
故f(n) 为 An * B 所得矩阵的最后一个元素
代码:
//Author LJH
//www.cnblogs.com/tenlee
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#define clc(a, b) memset(a, b, sizeof(a))
using namespace std;
const int inf = 0x3f;
const int INF = 0x3f3f3f3f;
const int maxn = 10;
int k, m;
void Init(int a[][maxn], int ans[][maxn])
{
for(int i = 0; i < 9; i++)
{
for(int j = 0; j < 10; j++)
{
a[i][j] = 0;
if(j-1 == i)
{
a[i][j] = 1;
}
}
}
for(int i = 0; i < maxn; i++)
{
for(int j = 0; j < maxn; j++)
{
if(i == j)
ans[i][j] = 1;
else
ans[i][j] = 0;
}
}
}
void matrix_mul(int a[][maxn], int b[][maxn])
{
int i, j, k;
int tmp[maxn][maxn] = {0};
for(i = 0; i < maxn; i++)
{
for(j = 0; j < maxn; j++)
{
for(k = 0; k < maxn; k++)
{
tmp[i][j] = (tmp[i][j] + a[i][k] * b[k][j] % m) % m;
}
}
}
for(i = 0; i < maxn; i++)
{
for(j = 0; j < maxn; j++)
{
a[i][j] = tmp[i][j];
}
}
/*for(int i = 0; i < maxn; i++)
{
for(int j = 0; j < maxn; j++)
printf("b %d ", a[i][j]);
puts("");
}*/
}
int quickPow(int a[maxn][maxn], int b[maxn], int ans[maxn][maxn], int n)
{
/*for(int i = 0; i < maxn; i++)
{
for(int j = 0; j < maxn; j++)
printf("%d ", a[i][j]);
puts("");
}*/
while(n)
{
if(n & 1) matrix_mul(ans, a);
matrix_mul(a, a);
n >>= 1;
}
/*for(int i = 0; i < maxn; i++)
{
for(int j = 0; j < maxn; j++)
printf("%d ", ans[i][j]);
puts("");
}*/
int sum = 0;
for(int i = 0; i < maxn; i++)
{
sum = (sum + i * ans[9][i]) % m;
}
return sum % m;
}
void func(int a[][maxn])
{
int d[50];
for(int i = 0; i < 10; i++)
d[i] = i;
for(int i = 10; i <= k; i++)
{
d[i] = 0;
for(int j = 0; j < 10; j++)
{
d[i] = (d[i] + a[9][j] * d[i-j-1] % m) % m;
}
printf("%d#%d ", i, d[i]);
}
puts("");
}
int main()
{
freopen("1.txt", "r", stdin);
int a[maxn][maxn], b[maxn], ans[maxn][maxn];
while(~scanf("%d %d\n", &k, &m))
{
Init(a, ans);
for(int i = 0; i < 10; i++)
{
scanf("%d", &a[9][9-i]);
}
//func(a);
if(k >= 10)
printf("%d\n", quickPow(a, b, ans, k-9));
else
printf("%d\n", k%m);
}
return 0;
}