http://acm.hdu.edu.cn/showproblem.php?pid=1757
A Simple Math Problem
If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .
Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.
In each case, there will be two lines.
In the first line , there are two positive integers k and m. ( k<2*10^9 , m < 10^5 )
In the second line , there are ten integers represent a0 ~ a9.
10 9999 1 1 1 1 1 1 1 1 1 1 20 500 1 0 1 0 1 0 1 0 1 0
45 104
很基础的矩阵快速幂。
矩阵乘法不会的自己百度吧
只需要知道初始矩阵和 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);这个方程转化成的系数矩阵,
第9项矩阵 *系数矩阵 =第10项矩阵(矩阵的第0行第0列表示 f(10))
f9 f8 f7 f6 f5 f4 f3 f2 f1 f0 a0 1 0 0 0 0 0 0 0 0 f10 f9 f8 f7 f6 f5 f4 f3 f2 f1
0 0 0 0 0 0 0 0 0 0 a1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 a2 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 a3 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 a4 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 乘以 a5 0 0 0 0 0 1 0 0 0 等于 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 a6 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 a7 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 a8 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
其中 f10 =a0*f9+a1*f8+a2*f7+......+a9*f0;
同理用第10项矩阵乘以系数矩阵就能得到第11项。
有第9项矩阵,让求第k项,所以成以系数矩阵 (k-9)次,就可以第k项。因为k很大,所以用快速幂。
所以叫做矩阵快速幂0.0。
奉上我的AC代码:
#include <iostream>
#include <queue>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 50000
#define LL long long
using namespace std;
int m;
struct node
{
LL a[15][15];
}a,ans;//a是方程转化成的系数矩阵,ans是初始矩阵。
node operator * (node b,node c)//自定义矩阵乘法
{
node d;
memset(d.a,0,sizeof(d.a));
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
{
for(int k=0;k<10;k++)
d.a[i][j]+=b.a[i][k]*c.a[k][j];
d.a[i][j]%=(LL)m;
}
return d;
}
void init()//矩阵初始化
{
memset(a.a,0,sizeof(a.a));
memset(ans.a,0,sizeof(ans.a));
for(int i=0;i<10;i++)
{
ans.a[0][i]=9LL-(LL)i;
scanf("%I64d",&a.a[i][0]);
a.a[i][i+1]=1LL;(1LL表示LL型的1)
}
}
int main()
{
int k;
while(~scanf("%d%d",&k,&m))
{
init();
if(k<10)
{
printf("%d\n",k%m);
continue;
}
k-=9;
while(k)
{
if(k%2)
ans= ans*a;
a= a*a;
k=k>>1;
}
printf("%I64d\n",ans.a[0][0]);
}
}