该题搞了一个晚上才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; }