HDU1757 A Simple Math Problem

HDU1757题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1757

这道题做了一下午- -,主要是卡在了矩阵构造上,该题的数据为( k<2*10^9 , m < 10^5 ),k很大,可以看出递推求出每一个f(k)肯定会超时的,所以想到了矩阵连乘,再运用二分法求解,够早的矩阵如下:

(f(9),f(8),f(7),f(6),f(5),f(4),f(3),f(2),f(1),f(0))*

HDU1757 A Simple Math Problem

=(f(10),f(9),f(8),f(7),f(6),f(5),f(4),f(3),f(2),f(1));

所以求f(10)只需求(f(9),f(8),f(7),f(6),f(5),f(4),f(3),f(2),f(1),f(0))*矩阵的一次方就行了,

若求f(k)当k>=10时,乘以矩阵的(k-9)次方即可;

然后再用二分法,求矩阵连乘的结果,AC代码如下:

#include<iostream>

using namespace std;

#include<string.h>

int d[10][10],t[10][10],t1[10][10];//数组t和t1都是中间量

void fun(int n,int m,int a[])//二分法  多练习多思考就会明白

{

    int i,j,k;

    if(n==1)//n=1的情况 终结递归的条件

    {

        memset(d,0,sizeof(d));

        for(i=0;i<10;i++)

         for(j=0;j<10;j++)

         {

             if(j==0)d[i][j]=a[i];

             if(j-i==1)d[i][j]=1;

         }

         return ;//返回

    }    

    if(n%2==0)//n为偶数时

    {

        n/=2;

        fun(n,m,a);

        

        for(i=0;i<10;i++)

         for(j=0;j<10;j++)

         t[i][j]=d[i][j];

        for(i=0;i<10;i++)

         for(j=0;j<10;j++)

         {

             int s=0;

             for(k=0;k<10;k++)

                 s+=t[i][k]*t[k][j];

             d[i][j]=s%m;    

         } 

         return ;

    }

    else        //n为奇数时

    {

        n/=2;

        fun(n,m,a);    

        

        for(i=0;i<10;i++)

         for(j=0;j<10;j++)

         t[i][j]=d[i][j];

        for(i=0;i<10;i++)

         for(j=0;j<10;j++)

         {

             int s=0;

             for(k=0;k<10;k++)

                  s+=t[i][k]*t[k][j];

             d[i][j]=s%m;     

         }                    

         //再乘以基本矩阵

         for(i=0;i<10;i++)//数组t和t1都是为了存取数组d的中间结果

          for(j=0;j<10;j++)

             t[i][j]=d[i][j];

         memset(t1,0,sizeof(t1));    

         for(i=0;i<10;i++)

          for(j=0;j<10;j++)

          {

              if(j==0)t1[i][j]=a[i];

              if(j-i==1)t1[i][j]=1;

          }           

         for(i=0;i<10;i++)

          for(j=0;j<10;j++)

          {

              int s=0;

              for(k=0;k<10;k++)

                   s+=t[i][k]*t1[k][j];

              d[i][j]=s%m;     

          }

          return ;

    }

}

int main()

{

    //freopen("d:\\1.txt","r",stdin);

    int k,m;

    int a[10];

    int i,s;

    while(scanf("%d%d",&k,&m)!=EOF)

    {

        for(i=0;i<10;i++)

         cin>>a[i];

         if(k<10)

         printf("%d\n",k%m);



         else

         {

            fun((k-9),m,a);    

            s=0;              

            for(i=0;i<10;i++)

            s+=(9-i)*d[i][0];  //直接求出结果

            

            cout<<s%m<<endl; 

         }

    }     

    

    return 0;

}

 

 

你可能感兴趣的:(simple)