完全被虐啊,见识太少,完全没有意识到取模必定会有循环节的问题,所以束手无策。。。。。
先暴力本地算出最外层取模的循环节,在依次往里推循环节,还需要注意两个long long型相乘的溢出问题,不过这道题好像没有这么极端的数据
code:
#include <cstdio>
#include <cstring>
#define LL __int64
using namespace std;
LL modular_multi(LL a, LL b, LL c) {
LL res;
res = 0;
while (b) {
if (b & 1) {
res += a;
if (res >= c) {
res -= c;
}
}
a <<= 1;
if (a >= c) {
a -= c;
}
b >>= 1;
}
return res;
}
struct Matrix
{
LL Mat[2][2];
void init()
{
memset(Mat,0,sizeof(Mat));
}
void unit()
{
init();
Mat[0][0]=Mat[1][1]=1;
}
Matrix()
{
init();
}
Matrix Mul(Matrix b,LL mod)
{
Matrix res;
res.init();
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
for(int k=0;k<2;k++)
{
res.Mat[i][j]=(res.Mat[i][j] + modular_multi(Mat[i][k],b.Mat[k][j],mod)) %mod;
}
}
}
return res;
}
Matrix Pow(LL exp,LL mod)
{
Matrix tmp=*this,res;
res.unit();
while(exp)
{
if( exp&1)
{
res=res.Mul(tmp,mod);
}
exp >>= 1;
tmp=tmp.Mul(tmp,mod);
}
return res;
}
void Print()
{
puts("------------------");
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
printf(" %I64d",Mat[i][j]);
}
puts("");
}
}
}a;
LL solve(LL n,LL mod)
{
if(n==0)
{
return 0;
}
return a.Pow(n-1,mod).Mat[0][0];
}
int main()
{
LL n,ans;
a.Mat[0][0]=3;
a.Mat[0][1]=1;
a.Mat[1][0]=1;
a.Mat[1][1]=0;
while(~scanf("%I64d",&n))
{
ans=solve(solve(solve(n,183120),222222224),1000000007);
printf("%I64d\n",ans);
}
return 0;
}