2012 ACM/ICPC Asia Regional Chengdu Online(hdu4291)

A Short problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 591    Accepted Submission(s): 230


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 <= 10 18), You should solve for 
g(g(g(n))) mod 10 9 + 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
 

Source
 

Recommend
liuyiding


g(g(g(n)))对1000000007求余得到的循环节222222224,那么g(g(n))对222222224求余后再计算g(g(g(n)))是相等的,以此类推,求g(g(g(n)))就是求g(g(g(n)%183120)%222222224)%1000000007.


先本地暴力求出分别对1000000007取余的循环节为222222224,然后再对222222224暴力求出循环节为183120,最后分别对三种求余进行矩阵连乘计算

循环节代码:

#include <iostream>
#include <stdio.h>
using namespace std;
const long long mod=1000000007;//求出循环节为222222224,然后改为222222224再求一次
int main()
{
    long long g1,g2,s;
    long long i=1;
    g1=0;g2=1;
    for(;;i++)
    {
    long long s=(3*g2+g1)%mod;
    g1=g2;g2=s;
    if(g1==0&&g2==1) break;
              }
    printf("%lld\n",i);
   system("pause");
   return 0; 
}



AC代码:

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdio>
using namespace std;
long long Mod;
const int MAX = 2;
typedef struct
{
    long long m[MAX][MAX];
} Matrix;
Matrix P =
{
    3,1,
    1,0,
};
Matrix I =
{
    1,0,
    0,1,
};
Matrix matrixmul(Matrix a,Matrix b)
{
    int i,j,k;
    Matrix c;
    for (i = 0 ; i < MAX; i++)
        for (j = 0; j < MAX; j++)
        {
            c.m[i][j] = 0;
            for (k = 0; k < MAX; k++)
                c.m[i][j] += (a.m[i][k]%Mod) * (b.m[k][j]%Mod);
            c.m[i][j] %= Mod;
        }
    return c;
}
Matrix quickpow(long long n)
{
    Matrix m = P, b = I;
    while (n >= 1)
    {
        if (n & 1)
            b = matrixmul(b,m);
        n = n >> 1;
        m = matrixmul(m,m);
    }
    return b;
}
int main()
{
    long long n;
    while(cin>>n)
    {
        if(n<=1)
        {
            cout<<n<<endl;
            continue;
        }
        Mod=183120;
        Matrix C;
        C=quickpow(n-1);
        n=C.m[0][0];
        if(n<=1)
        {
            cout<<n<<endl;
            continue;
        }
        Mod=222222224;
        Matrix C1;
        C1=quickpow(n-1);
        n=C1.m[0][0];
        if(n<=1)
        {
            cout<<n<<endl;
            continue;
        }
        Mod=1000000007;
        Matrix C2;
        C2=quickpow(n-1);
        n=C2.m[0][0]%Mod;
        cout<<n<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值