zoukankan      html  css  js  c++  java
  • 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;
    }

     

  • 相关阅读:
    c# 调用C++动态库 问题
    Web应用简易框架。
    【转】SVN历史版本删除(为SVN库瘦身)
    程序员7武器序
    小系统单据自动生成存储过程
    【转】数据库和数据仓库的区别
    jQuery之extend 函数
    .NET单元测试断言(Assert)
    c#类型转换操作符:as和is
    oracle 表数据合并
  • 原文地址:https://www.cnblogs.com/hsqdboke/p/2472110.html
Copyright © 2011-2022 走看看