zoukankan      html  css  js  c++  java
  • hdu4291 暴力循环节+矩阵快速幂

    题意:
          给你一个关系式,x[n] = 3*x[n-1] + x[n-2],求x(x(x[n]))%1000000007.


    思路:

          做这个题目要明确一点,就是对于取余操作大多数时候都会出现循环节的情况,尤其是对于像这个题目的转换公式,数据有规律递增,那么也就是说0 1 1 ....等再次出现0 1的时候也就是一定找了循环节,对于这个题目我们找循环节主要不是为了防止超时,而是为了得到正确的答案,因为x[n]很大的时候就的模拟大数,就麻烦了,我们只要找到每一层的循环节,就能把数据弄小,就可以跑三次矩阵快速A掉这个题目了。

    下面给出暴力循环节代码(暴力第二层的,最内层把10..7改成第二层的MOD就行了)

    #include<stdio.h>


    int main ()
    {
       __int64 a = 0 ,b = 1 ,c;
       for(__int64 i = 3 ; ;i ++)
       {
          c = (b * 3 + a)%1000000007;
          a = b ,b = c;
          if(a == 0 && b == 1)
          {
              printf("%I64d " ,i - 2);
              break;
          }
       }
       getchar();
       return 0;
    }
          
    暴力后得到最内侧的MOD = 183120
    第二层 MOD = 222222224
    最外层给了 MOD = 1000000007


    AC代码


    #include<stdio.h>
    #include<string.h>
    
    __int64 MOD1 = 183120;
    __int64 MOD2 = 222222224;
    __int64 MOD3 = 1000000007;
    
    __int64 MOD;
    typedef struct
    {
       __int64 mat[5][5];
    }A;
    
    A mat_mat(A a ,A b)
    {
       A c;
       memset(c.mat ,0 ,sizeof(c.mat));
       for(int k = 1 ;k <= 2 ;k ++)
       for(int i = 1 ;i <= 2 ;i ++)
       if(a.mat[i][k])
       for(int j = 1 ;j <= 2 ;j ++)
       c.mat[i][j] = (c.mat[i][j] + a.mat[i][k]  * b.mat[k][j]) % MOD;
    
      
       return c;
    } 
    
    A quick_mat(A a ,__int64 b)
    {
       A c;
       memset(c.mat ,0 ,sizeof(c.mat));
       c.mat[1][1] = c.mat[2][2] = 1;
       while(b)
       {
          if(b & 1) c = mat_mat(c ,a);
          a = mat_mat(a ,a);
          b >>= 1;
       }
       return c;
    }
    
    int main ()
    {
        __int64 n ,i;
        A aa ,bb;
        aa.mat[1][1] = 0 ,aa.mat[1][2] = 1;
        aa.mat[2][1] = 1 ,aa.mat[2][2] = 3;
        while(~scanf("%I64d" ,&n))
        {
            if(n == 0){printf("0
    ");continue;}
            if(n == 1){printf("1
    ");continue;}
            MOD = MOD1;
            bb = quick_mat(aa ,n - 1);
            n = (0 * bb.mat[1][2] + 1 * bb.mat[2][2])% MOD;
            
            if(n == 0){printf("0
    ");continue;}
            if(n == 1){printf("1
    ");continue;}
            MOD = MOD2;
            bb = quick_mat(aa ,n - 1);
            n = (0 * bb.mat[1][2] + 1 * bb.mat[2][2])% MOD;
        
            if(n == 0){printf("0
    ");continue;}
            if(n == 1){printf("1
    ");continue;}
            MOD = MOD3;
            bb = quick_mat(aa ,n - 1);
            n = (0 * bb.mat[1][2] + 1 * bb.mat[2][2])% MOD;
            
            printf("%I64d
    " ,n);
        }
        return 0;
    }
            
             
       
       
    






  • 相关阅读:
    查询自动生成Guid列
    Appium运行时报does not have permission android.permission.CLEAR_APP_USER_DATA to clear data
    小米手机
    SoapUI简介和入门实例解析
    Postman高级应用——流程控制、调试、公共函数、外部数据文件
    Postman高级应用——串行传参和动态传参详解
    Fiddler抓包工具使用详解
    接口测试简介
    soapui基础知识
    接口测试文档规范
  • 原文地址:https://www.cnblogs.com/csnd/p/12062826.html
Copyright © 2011-2022 走看看