zoukankan      html  css  js  c++  java
  • hdu 4291 A Short problem (矩阵快速幂+循环节)

    Problem Description
      According to a research, VIM users tend to have shorter fingers, compared with Emacs users.
      Hence they prefer problems short, too. Here is a short one:
      Given n (1 <= n <= 1018), You should solve for 
    g(g(g(n))) mod 109 + 7

      where
    g(n) = 3g(n - 1) + g(n - 2)

    g(1) = 1

    g(0) = 0
     

    Input
      There are several test cases. For each test case there is an integer n in a single line.
      Please process until EOF (End Of File).
     

    Output
      For each test case, please print a single line with a integer, the corresponding answer to this case.
     

    Sample Input
    0
    1
    2
     

    Sample Output
    0
    1
    42837
     
        这题主要找循环节,mo1=1000000007,mo2=222222224,mo3=183120;找到循环节后只要用矩阵快速幂就可以了,下面有找循环节代码。
        由于找循环节很耗时,所以找到后直接写出来,不用写在代码里。
     
     找循环节:
     
     1 #include<cstdio>
     2 long long mo1=1000000007;
     3 int main()
     4 {
     5     long long i=1,a=1,b=0,c;
     6     while (i)
     7     {
     8         c=(3*a+b)%mo1;
     9         b=a;
    10         a=c;
    11         if (a==1&&b==0)
    12         {
    13             printf("%I64d
    ",i);
    14             break;
    15         }
    16         i++;
    17     }
    18 }
    View Code


    ac代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 long long mo1=1000000007;
     6 long long mo2=222222224;
     7 long long mo3=183120;
     8 long long s1[3][3],s2[3][3],s3[3][3];
     9 long long f(long long n,long long mo)
    10 {
    11     int i,j,k;
    12     s1[0][0]=s2[0][0]=3;
    13     s1[0][1]=s2[0][1]=1;
    14     s1[1][0]=s2[1][0]=1;
    15     s1[1][1]=s2[1][1]=0;
    16     n-=2;
    17     while (n)
    18     {
    19         if (n&1)
    20         {
    21             memset(s3,0,sizeof(s3));
    22             for (k=0;k<2;k++)
    23             for (i=0;i<2;i++){if (!s1[i][k]) continue;
    24             for (j=0;j<2;j++)
    25             s3[i][j]=(s3[i][j]+s1[i][k]*s2[k][j])%mo;}
    26             for (i=0;i<2;i++)
    27             for (j=0;j<2;j++) s2[i][j]=s3[i][j];
    28         }
    29         memset(s3,0,sizeof(s3));
    30         for (k=0;k<2;k++)
    31         for (i=0;i<2;i++) {if (!s1[i][k]) continue;
    32         for (j=0;j<2;j++)
    33         s3[i][j]=(s3[i][j]+s1[i][k]*s1[k][j])%mo;}
    34         for (i=0;i<2;i++)
    35         for (j=0;j<2;j++) s1[i][j]=s3[i][j];
    36         n>>=1;
    37     }
    38     return s2[0][0];
    39 }
    40 int main()
    41 {
    42     long long n;
    43     long long ans;
    44     while (~scanf("%I64d",&n))
    45     {
    46         if (n==0) {printf("0
    ");continue;}
    47         if (n==1) {printf("1
    ");continue;}
    48         ans=f(n,mo3);
    49         if (ans>=2) //一定要有,不然ans<2时函数就会死循环。
    50         ans=f(ans,mo2);
    51         if (ans>=2)
    52         ans=f(ans,mo1);
    53         printf("%I64d
    ",ans);
    54     }
    55 }
  • 相关阅读:
    Vim作者创造新编程语言Zimbu
    Google Maps API编程资源大全
    好网收集的地址
    三种模拟自动登录和提交POST信息的实现方法
    解析VMware三种网络连接方式
    PostgreSQL 创建帐号,数据库,权限
    LINUX目录详解
    Linux流媒体服务器安装配置
    用RAMDISK来提高PostgreSQL访问速度
    PostgreSQL 集群复制方案之使用pgq和londiste工具包
  • 原文地址:https://www.cnblogs.com/pblr/p/4759823.html
Copyright © 2011-2022 走看看