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))*

=(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;
}

 

原文地址:https://www.cnblogs.com/hsqdboke/p/2472110.html