二分幂:如计算a^n;如果n为偶数,则计算a^n/2(递归到n=0),再计算(a^n/2)(a^n/2),就可得出结果;如果n为奇数,则先计算a^(n-1)/2(递归到n=0),再计算(a^(n-1)/2)*(a^(n-1)/2)a,就可得出结果。
long long fun(int a,int b)
{
if (b==0)
return 1;
if (b==1)
return a;
long long ans=fun(a,b/2);
ans*=ans;
if (b%2==1)
ans*=a;
return ans;
}
快速幂:如计算经典的2^11;11的二进制为1011,2^3*1+2^2*0+2^1*1+2^0*1,2^(2^3*1+2^2*0+2^1*1+2^0*1)。
一般方法:
long long fun( int a, int b )
{
long long r = 1;
int base = a;
while( b != 0 )
{
if( b % 2 )//判断奇偶性
r *= base;
base *= base;
b /= 2;//与b>>1相同
}
return r;
}
位运算:
long long fun( int a, int b )
{
long long r = 1;
int base = a;
while( b != 0 )
{
if( b & 1 )//判断奇偶性
{
r *= base;
}
base *= base;
b >>= 1;//与b/2相同
}
return r;
}
矩阵快速幂:
/**************************************************************
FZU 2198 矩阵快速幂 + 矩阵乘法优化 + 打表 + 广义Fibonacci数列找循环节
F(n) = a * F(n - 1) + b * F(n - 2)
a^2 + 4b是模p的二次剩余时,枚举n = p - 1的因子
a^2 + 4b是模p的二次非剩余时,枚举n = (p + 1)(p - 1)的因子
找到最小的循环节
**************************************************************/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const LL mod = 1000000007;
struct Matrix
{
int row, col;
LL m[4][4];
void init(int row, int col)
{
this->row = row;
this->col = col;
for (int i = 0; i < row; ++i)
for (int j = 0; j < col; ++j)
m[i][j] = 0;
}
} A, pp[66], ans;
Matrix operator*(const Matrix & a, const Matrix& b)
{
Matrix res;
res.init(a.row, b.col);
for (int k = 0; k < a.col; ++k)
{
for (int i = 0; i < res.row; ++i)
{
if (a.m[i][k] == 0 ) continue;
for (int j = 0; j < res.col; ++j)
{
if (b.m[k][j] == 0 ) continue;
res.m[i][j] = (a.m[i][k] * b.m[k][j] + res.m[i][j]) % mod;
}
}
}
return res;
}
void init()
{
Matrix qq;
A.init(3, 1);
A.m[0][0] = 7;
A.m[1][0] = 1;
A.m[2][0] = 1;
qq.init(3, 3);
qq.m[0][0] = 6;
qq.m[0][1] = -1;
qq.m[0][2] = 1;
qq.m[1][0] = 1;
qq.m[2][2] = 1;
pp[0] = qq;
for (int i = 1; i < 64; i++)
pp[i] = pp[i - 1] * pp[i - 1];
}
void Cal(LL a)
{
for (int i = 0; a; i++, a >>= 1)
{
if (a & 1)
{
ans = pp[i] * ans;
}
}
return ;
}
int main()
{
int T;
LL n;
init();
scanf("%d", &T);
while (T--)
{
scanf("%I64d", &n);
ans = A;
LL tmp = (n - 1) % 500000003;
Cal(tmp);
printf("%I64d\n", (ans.m[0][0] - 1 + mod) % mod);
}
return 0;
}