该题搞了一个晚上才A了它,刚开始一直不能出正确结果,总认为是我的二分哪里错了,修改了几个小时,还重敲了,后来才发现是矩阵建反了,该题最重要的是建立矩阵,如果矩阵建立好了,就万事顺利了,怎样建立这个矩阵了,我们来讨论一下(n>10),f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
我们来看个图:、
矩阵A 矩阵B
0 1 0 0 0 0 0 0 0 0 f0 f1
0 0 1 0 0 0 0 0 0 0 f1 f2
0 0 0 1 0 0 0 0 0 0 f2 f3
0 0 0 0 1 0 0 0 0 0 * f3 ----------> f4
0 0 0 0 0 1 0 0 0 0 f4 f5
0 0 0 0 0 0 1 0 0 0 f5 f6
0 0 0 0 0 0 0 1 0 0 f6 f7
0 0 0 0 0 0 0 0 1 0 f7 f8
0 0 0 0 0 0 0 0 0 1 f8 f9
a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 f9 f10
我们看到规律了,每次要到下次个A*B,以此类推则由A*A*A.......A*B;
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int num[33][11][11],count;
void Matrix( int t, int m ) //二分法
{
if( t==1 )
return ;
Matrix( t/2,m );
if( t%2 )//奇数
{
int number[11][11]={0};
count++;
for( int i=1; i<=10; i++ )
for( int j=1; j<=10; j++ )
for( int k=1; k<=10; k++ )
num[count][i][j]=(num[count][i][j]+num[count-1][i][k]*num[count-1][k][j])%m;
for( int i=1; i<=10; i++ )
for( int j=1; j<=10; j++ )
for( int k=1; k<=10; k++ )
number[i][j]=(number[i][j]+num[count][i][k]*num[1][k][j])%m;
for( int i=1; i<=10; i++ )
{
for( int j=1; j<=10; j++ )
{
num[count][i][j]=number[i][j];
}
}
}
else//偶数
{
count++;
for( int i=1; i<=10; i++ )
{
for( int j=1; j<=10; j++ )
{
for( int k=1; k<=10; k++ )
num[count][i][j]=(num[count][i][j]+num[count-1][i][k]*num[count-1][k][j])%m;
}
}
}
}
int main()
{
int t,m;
while( scanf( "%d%d",&t,&m )!=EOF )
{
memset( num,0,sizeof( num ) );
for( int i=1; i<=9; i++ )//建立矩阵
{
num[1][i][i+1]=1;
}
for( int i=10;i>=1; i-- )
scanf( "%d",&num[1][10][i] );
if( t<10 )
printf( "%d\n",t );
else
{
count=1;
Matrix( t-9,m );
int sum=0;
for( int i=1; i<=10; i++ )
{
sum=(sum+num[count][10][i]*(i-1))%m;
}
printf( "%d\n",sum );
}
}
return 0;
}