HDU----(4291)A Short problem(快速矩阵幂)

A Short problem

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

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

Source

2012 ACM/ICPC Asia Regional Chengdu Online

此题出得比较精妙,

分析:假设g(g(g(n)))=g(x),x可能超出范围,但是由于mod 10^9+7,所以可以求出x的循环节

求出x的循环节后,假设g(g(g(n)))=g(x)=g(g(y)),即x=g(y),y也可能非常大,但是由x的循环节可以求出y的循环节

如何求循环节点:

 1 /*采用事先处理自己可以求出来*/
 2 LL work(LL mod){
 3   LL a=0,b=1;
 4     for(LL i=2;;++i)
 5     {
 6       a=(b*3+a)%mod;
 7         a=a^b;
 8         b=a^b;
 9         a=a^b;
10         if(a == 0 && b == 1)  return i;
11  }

所以依次将mod1带入得到mod2=222222224;

然后将mod2带入得到mod3=183120;

然后就是快速矩阵了。

代码:

 1 //#define LOCAL
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #define LL __int64
 6 using namespace std;
 7 const int mod1 =1000000007;
 8 const int mod2=222222224;
 9 const int mod3=183120;
10
11 LL mat[2][2];
12 LL ans[2][2];
13 LL n;
14
15 void Matrix(LL a[][2],LL b[][2],LL mod)
16 {
17     LL cc[2][2]={0};
18     for(int i=0;i<2;i++)
19     {
20       for(int j=0;j<2;j++)
21       {
22           for(int k=0;k<2;k++)
23         {
24             cc[i][j]=(cc[i][j]+a[i][k]*b[k][j])%mod;
25         }
26       }
27     }
28     for(int i=0;i<2;i++)
29     {
30       for(int j=0;j<2;j++)
31       {
32           a[i][j]=cc[i][j];
33       }
34     }
35 }
36
37 void pow(LL w,LL mod)
38 {
39   while(w>0)
40   {
41     if(w&1) Matrix(ans,mat,mod);
42      w>>=1;
43      if(w==0)break;
44      Matrix(mat,mat,mod);
45   }
46 }
47 void input(LL w,LL mod)
48 {
49      mat[0][0]=3;
50      mat[0][1]=mat[1][0]=1;
51      mat[1][1]=0;
52      ans[0][0]=ans[1][1]=1;
53      ans[0][1]=ans[1][0]=0;
54      pow(w,mod);
55 //     printf("%I64d\n",ans[0][0]);
56 }
57 void work(int i,__int64 w)
58 {
59   if(i==4||w==0||w==1)
60   {
61       if(w==0)
62          printf("0\n");
63       else if(w==1)
64           printf("1\n");
65       else
66       printf("%I64d\n",ans[0][0]);
67       return ;
68   }
69   LL mod;
70   if(i==1)mod=mod3;
71   else if(i==2)mod=mod2;
72   else if(i==3)mod=mod1;
73   input(w-1,mod);
74   work(i+1,ans[0][0]);
75 }
76 int main()
77 {
78   #ifdef LOCAL
79    freopen("test.in","r",stdin);
80   #endif
81   while(scanf("%I64d",&n)!=EOF)
82      work(1,n);
83  return 0;
84 }

时间: 2024-11-05 11:23:02

HDU----(4291)A Short problem(快速矩阵幂)的相关文章

HDU 4291 A Short problem(矩阵+循环节)

A Short problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2711    Accepted Submission(s): 951 Problem Description According to a research, VIM users tend to have shorter fingers, compared

hdu 4291 A Short problem(矩阵+取模循环节)

A Short problem                                                          Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1785    Accepted Submission(s): 651 Problem Description According to a r

HDU 4291 A Short problem

A Short problem Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 429164-bit integer IO format: %I64d      Java class name: Main According to a research, VIM users tend to have shorter fingers, compared with Em

HDU 4291 A Short problem(矩阵快速幂+循环节)

题目链接": http://acm.hdu.edu.cn/showproblem.php?pid=4291 题意: g(0)=0,g(1)=1; g(n) = 3g(n - 1) + g(n - 2): 求g(g(g(n))) mod 109 + 7 分析: 首先我们得认识到,如果一层一层算是必定会超时的. 其次,取模运算是有循环节的. step1我们找出g(x)%1000000007的循环节 mod1 step2 设g(g(n)) = g(x) x=g(n) 对mod1 取模得到mod2. 剩

HDU 4291 A Short problem (2012成都网络赛,矩阵快速幂+循环节)

链接: click here~~ 题意: 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

HDU 4291 A Short problem 又是一道神奇的矩阵

首先要知道一个姿势,对于Fib数列这类的东西,只要取余就一定会出现循环节.所以上来就直接暴力打表找规律就好了. MOD = 1000000007 发现循环节是 222222224. MOD = 2222222227 发现循环节是 183120 然后这个问题就解决了. 不要问我为啥会出现循环节,我也不会证明... ----------------------------------分割线---------------------------------- 我好像会证明了,试着证一发. 设有一个递推

HDU 4291 A Short problem 短问题 (递推,微变型)

题意:给出递推式 g(n) = 3g(n - 1) + g(n - 2),且g(1) = 1,g(0) = 0.求g( g( g(n))) mod 109 + 7. 思路:要求的g( g( g(n)))一共里外3层.看到时间限制1s,数据最大10^18,必定不能老实递推,要么有循环,要么用通项公式.这里用通项公式太麻烦了,数字不好算,而g(n)%109 + 7是有规律的, 在n=222222224之后会出现循环,也就是n=0和n=222222224的g(n)是一样的,这是最外层.那么也就是说在g

快速矩阵幂+DFS构造矩阵+大数 ACdream1214 Nice Patterns Strike Back

传送门:点击打开链接 题意:告诉你矩阵大小是n*m,要求矩阵中不能有2*2的白色子矩阵或者黑色子矩阵,最后种类数模P 思路:如果不是大数,这道题还是非常有意思的..对于专门卡C++的题目也是醉了...因为n太大了,而m最大也只有5,很明显是大数上的快速矩阵幂. 问题是如何构造出矩阵出来,之前做过骨牌的题目,就是利用DFS来构造的,感觉这道题在思路上是一样的,同样也是利用DFS先构造出矩阵 然后直接大数+快速矩阵幂撸一发就行了 #include<map> #include<set>

CodeForces621E 快速矩阵幂优化dp

有时些候在用快速矩阵幂优化dp的时候,它的矩阵乘法是不那么容易被具体为题目背景的意思的,大多数时候难以理解矩阵之间相乘的实际意义,正如有时候我们不知道现在在做手头这些事情的意义,但倘若是因一个目标而去做的,正如快速矩阵幂最终会计算出答案一样,我们也最终会在这些不明意义的事情中实现目标. 题意:有 bb 个格子,每个格子有 nn 个数字,各个格子里面的数字都是相同的. 求从 bb 个格子中各取一个数字, 构成一个 bb 位数, 使得这个 bb 位数模 xx 为 kk 的方案数(同一格子内相同的数字