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

时间:2023-01-28 15:09:03

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
 
此题出得比较精妙,
分析:假设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的循环节

如何求循环节点:

 /*采用事先处理自己可以求出来*/
LL work(LL mod){
LL a=,b=;
for(LL i=;;++i)
{
a=(b*+a)%mod;
a=a^b;
b=a^b;
a=a^b;
if(a == && b == ) return i;
}

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

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

然后就是快速矩阵了。

代码:

 //#define LOCAL
#include<iostream>
#include<cstdio>
#include<cstring>
#define LL __int64
using namespace std;
const int mod1 =;
const int mod2=;
const int mod3=; LL mat[][];
LL ans[][];
LL n; void Matrix(LL a[][],LL b[][],LL mod)
{
LL cc[][]={};
for(int i=;i<;i++)
{
for(int j=;j<;j++)
{
for(int k=;k<;k++)
{
cc[i][j]=(cc[i][j]+a[i][k]*b[k][j])%mod;
}
}
}
for(int i=;i<;i++)
{
for(int j=;j<;j++)
{
a[i][j]=cc[i][j];
}
}
} void pow(LL w,LL mod)
{
while(w>)
{
if(w&) Matrix(ans,mat,mod);
w>>=;
if(w==)break;
Matrix(mat,mat,mod);
}
}
void input(LL w,LL mod)
{
mat[][]=;
mat[][]=mat[][]=;
mat[][]=;
ans[][]=ans[][]=;
ans[][]=ans[][]=;
pow(w,mod);
// printf("%I64d\n",ans[0][0]);
}
void work(int i,__int64 w)
{
if(i==||w==||w==)
{
if(w==)
printf("0\n");
else if(w==)
printf("1\n");
else
printf("%I64d\n",ans[][]);
return ;
}
LL mod;
if(i==)mod=mod3;
else if(i==)mod=mod2;
else if(i==)mod=mod1;
input(w-,mod);
work(i+,ans[][]);
}
int main()
{
#ifdef LOCAL
freopen("test.in","r",stdin);
#endif
while(scanf("%I64d",&n)!=EOF)
work(,n);
return ;
}