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
输入
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).
输出
For each test case, please print a single line with a integer, the corresponding answer to this case.
输入样例
0
1
2
输出样例
0
1
42837
---------------------------------------------------------
#include<bits/stdc++.h>
using namespace std;
#define mod1 1000000007
#define mod2 222222224
#define mod3 183120
typedef long long ll;
struct node
{
ll a[15][15];
};
node multi(node a, node b, ll mod)
{
node c={0};
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
for(int k=0;k<5;k++)
{
c.a[i][j] = (c.a[i][j] + (a.a[i][k] * b.a[k][j]))%mod;
}
}
}
return c;
}
node pow_mod(node a, ll n, ll mod)
{
node b = {0};
for(int i=0;i<5;i++)
{
b.a[i][i] = 1;
}
while(n>0)
{
if(n&1)
{
b = multi(a, b, mod);
}
a = multi(a, a, mod);
n>>=1;
}
return b;
}
int main()
{
ll x, ans = 0;
node b, c;
node n={0}, m={0};
n.a[0][0] = 3;
n.a[0][1] = 1;
n.a[1][0] = 1;
m.a[0][0] = 1;
m.a[1][1] = 1;
while(~scanf("%lld", &x))
{
if(x==0)
{
printf("0\n");
continue;
}
else if(x==1)
{
printf("1\n");
continue;
}
else
{
b = n,c = m;
b = pow_mod(b, x-1, mod3);
c = multi(b, c, mod3);
ans = c.a[0][0];
ans = ans + mod3;
b = n, c = m;
b = pow_mod(b, ans-1, mod2);
c = multi(b, c, mod2);
ans = c.a[0][0];
ans = ans + mod2;
b = n, c = m;
b = pow_mod(b, ans-1, mod1);
c = multi(b, c, mod1);
ans = c.a[0][0];
printf("%lld\n", c.a[0][0]%mod1);
}
}
return 0;
}