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
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).
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
1
2
Sample Output
0
1
42837
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 ;
}