快速幂
由 于 c p p 中 c m a t h 库 p o w 函 数 是 d o u b l e 型 , d o u b l e 转 i n t 精 度 丢 失 会 有 错 误 , 因 此 采 用 此 算 法 , 时 间 复 杂 度 O ( log n ) 由于cpp中cmath库pow函数是double型,double转int精度丢失会有错误,因此采用此算法,\\时间复杂度O(\log n) 由于cpp中cmath库pow函数是double型,double转int精度丢失会有错误,因此采用此算法,时间复杂度O(logn)
#define ll long long
ll power(ll a, ll n)
{
ll ans = 1, t = a;
for (; n; n >>= 1, t *= t)
if(n & 1) ans *= t;
return ans;
}
快速幂取模(二进制)
首
先
证
明
:
(
a
∗
b
)
m
o
d
c
=
[
(
a
m
o
d
c
)
∗
(
b
m
o
d
c
)
]
m
o
d
c
首先证明:(a*b)\ mod\ c=\left[(a\ mod\ c)*(b\ mod\ c)\right]\ mod\ c
首先证明:(a∗b) mod c=[(a mod c)∗(b mod c)] mod c
S
u
p
p
o
s
e
:
a
m
o
d
c
=
d
,
b
m
o
d
c
=
e
t
h
e
n
a
=
m
c
+
d
,
b
=
n
c
+
e
S
o
(
a
∗
b
)
m
o
d
c
=
(
m
c
+
d
)
∗
(
n
c
+
e
)
m
o
d
c
=
(
d
⋅
e
)
m
o
d
c
Suppose:a\ mod\ c=d,b\ mod\ c=e\\then\quad a=mc+d,b=nc+e\\So\quad(a*b)\ mod\ c=(mc+d)*(nc+e)\ mod\ c=(d\cdot e)\ mod\ c
Suppose:a mod c=d,b mod c=ethena=mc+d,b=nc+eSo(a∗b) mod c=(mc+d)∗(nc+e) mod c=(d⋅e) mod c
结
合
:
结合:
结合:
a
b
m
o
d
c
=
(
(
a
2
)
b
2
)
m
o
d
c
b
∈
2
k
,
k
∈
N
a
b
m
o
d
c
=
(
(
a
2
)
b
2
×
a
)
m
o
d
c
b
∈
2
k
−
1
,
k
∈
N
a^b\ mod\ c=((a^2)^\frac{b}{2})\ mod\ c\quad b\in2k,k\in N\\ a^b\ mod\ c=((a^2)^\frac{b}{2}\times a)\ mod\ c\quad b\in2k-1,k\in N
ab mod c=((a2)2b) mod cb∈2k,k∈Nab mod c=((a2)2b×a) mod cb∈2k−1,k∈N
#define ll long long
ll mod(ll x, ll n, ll m)
{
ll ans = 1;
for (x %= m; n; n >>= 1, x = x * x % m)
if (n & 1) ans = (ans % m) * (x % m) % m;
return ans;
}
十进制快速幂
#include <cstdio>
#include <cstring>
#define ll long long
const int N = 1e4 + 5;
ll a, mod, ans = 1;
char num[N];
void reverse(char *s)
{
char tmp;
int n = strlen(s);
for(int i = 0; i < n / 2; ++i){
tmp = s[i];
s[i] = s[n - 1 - i];
s[n - 1 - i] = tmp;
}
}
ll mpow(ll a, ll n, ll mod) {
ll res;
for (res = 1; n; n >>= 1, a = a * a % mod)
if (n & 1)
res = res * a % mod;
return res;
}
int main ()
{
scanf("%lld%s%lld", &a, num, &mod);
ll base = a;
int len = strlen(num);
reverse(num);
for (int i = 0; i < len; ++i) {
ans = ans * mpow(base, num[i] - '0', mod) % mod;
base = mpow(base, 10, mod) % mod;
}
printf ("%lld\n", ans);
return 0;
}
指数循环节降幂
对
于
a
n
s
=
2
n
m
o
d
m
,
1
≤
n
≤
1
0
100000
,
1
≤
m
≤
1
0
6
对于ans=2^n\ mod\ m,1\leq n\leq10^{100000},1\leq m \leq10^6
对于ans=2n mod m,1≤n≤10100000,1≤m≤106
可
利
用
降
幂
公
式
:
a
b
m
o
d
c
=
a
b
m
o
d
φ
(
c
)
+
φ
(
c
)
m
o
d
c
(
b
≥
φ
(
c
)
)
可利用降幂公式:a^b\ mod\ c=a^{b\ mod\ \varphi(c)+\varphi(c)}mod\ c\quad(b\geq \varphi(c))
可利用降幂公式:ab mod c=ab mod φ(c)+φ(c)mod c(b≥φ(c))
#include <cstdio>
#define ll long long
const int Mod = 1e9 + 7;
const int MAX_N = 1e5 + 5;
ll phi(ll x)
{
ll ans = x;
for (int i = 2; i * i <= x; ++i) {
if(x % i == 0) {
ans -= ans / i;
while (x % i == 0) x /= i;
}
}
if(x > 1) ans -= ans / x;
return ans;
}
ll qpow(ll a, ll n, ll mod)
{
ll ans = 1;
for(; n; n >>= 1, a = a * a % mod)
if(n & 1) ans = ans * a % mod;
return ans;
}
int main()
{
char a[MAX_N];
scanf("%s", a);
ll eu = phi(mod), tmp = 0;
for(int i = 0; a[i]; ++i) {
tmp = (tmp * 10 + a[i] - '0') % eu;
}
tmp += eu;
printf("%lld\n", qpow(2, tmp, Mod));
return 0;
}
矩阵快速幂
(
a
11
a
12
⋯
a
1
n
a
21
a
22
⋯
a
2
n
⋮
⋮
⋱
⋮
a
n
1
a
n
2
⋯
a
n
n
)
∗
(
b
11
b
12
⋯
b
1
n
b
21
b
22
⋯
b
2
n
⋮
⋮
⋱
⋮
b
n
1
b
n
2
⋯
b
n
n
)
=
(
c
11
c
12
⋯
c
1
n
c
21
c
22
⋯
c
2
n
⋮
⋮
⋱
⋮
c
n
1
c
n
2
⋯
c
n
n
)
c
i
j
=
∑
k
=
1
n
a
i
k
∗
b
k
j
\begin{pmatrix}a_{11} & a_{12} & \cdots & a_{1n}\\a_{21}&a_{22}&\cdots&a_{2n}\\ \vdots & \vdots & \ddots & \vdots\\ \ a_{n1} & a_{n2} & \cdots & a_{nn}\end{pmatrix}* \begin{pmatrix}b_{11} & b_{12} & \cdots & b_{1n}\\ \ b_{21}&b_{22}&\cdots&b_{2n}\\ \vdots & \vdots & \ddots & \vdots\\ \ b_{n1} & b_{n2} & \cdots & b_{nn}\end{pmatrix}= \begin{pmatrix}c_{11} & c_{12} & \cdots & c_{1n}\\ \ c_{21}&c_{22}&\cdots&c_{2n}\\ \vdots & \vdots & \ddots & \vdots\\c_{n1} & c_{n2} & \cdots & c_{nn}\end{pmatrix}\\c_{ij}=\sum^n_{k=1}a_{ik}*b_{kj}
⎝⎜⎜⎜⎛a11a21⋮ an1a12a22⋮an2⋯⋯⋱⋯a1na2n⋮ann⎠⎟⎟⎟⎞∗⎝⎜⎜⎜⎛b11 b21⋮ bn1b12b22⋮bn2⋯⋯⋱⋯b1nb2n⋮bnn⎠⎟⎟⎟⎞=⎝⎜⎜⎜⎛c11 c21⋮cn1c12c22⋮cn2⋯⋯⋱⋯c1nc2n⋮cnn⎠⎟⎟⎟⎞cij=k=1∑naik∗bkj
则可得递推式:
(
1
)
f
n
=
a
f
n
−
1
+
b
f
n
−
2
+
c
(
a
b
1
1
0
0
0
0
1
)
∗
(
f
n
−
1
f
n
−
2
c
)
=
(
f
n
f
n
−
1
c
)
(1)f_n=af_{n-1}+bf_{n-2}+c\\ \begin{pmatrix}a&b&1\\1&0&0\\0&0&1\end{pmatrix}*\begin{pmatrix}f_{n-1}\\f_{n-2}\\c\end{pmatrix}=\begin{pmatrix}f_{n}\\f_{n-1}\\c\end{pmatrix}
(1)fn=afn−1+bfn−2+c⎝⎛a10b00101⎠⎞∗⎝⎛fn−1fn−2c⎠⎞=⎝⎛fnfn−1c⎠⎞
(
2
)
f
n
=
c
n
−
f
n
−
1
(
−
1
c
0
c
)
∗
(
f
n
−
1
c
n
−
1
)
=
(
f
n
c
n
)
(2)f_n=c^n-f_{n-1}\\ \begin{pmatrix}-1&c\\0&c\end{pmatrix}*\begin{pmatrix}f_{n-1}\\c^{n-1}\end{pmatrix}=\begin{pmatrix}f_{n}\\c^n\end{pmatrix}
(2)fn=cn−fn−1(−10cc)∗(fn−1cn−1)=(fncn)
typedef vector<int> vec;
typedef vector<vec> mat;
#define ll long long
const int M = 10000;
mat mul(mat &a, mat &b)
{
mat c(a.size(), vec(b[0].size()));
for(int i = 0; i < a.size(); ++i) {
for(int k = 0; k < b.size(); ++k) {
for(int j = 0; j < b[0].size(); ++j) {
c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % M;
}
}
}
return c;
}
mat pow(mat a, int n)
{
mat b(a.size(), vec(a.size()));
for(int i = 0; i < a.size(); ++i) {
b[i][i] = 0;
}
while(n) {
if(n & 1) b = mul(b, a);
a = mul(a, a);
n >>= 1;
}
return b;
}
#include <iostream>
#include <cstring>
using namespace std;
#define ll long long
#define N 4
struct mat
{
ll m[N][N];
}t, tmp;
mat mul(mat a, mat b)
{
mat res;
memset(res.m, 0, sizeof(res.m));
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 2; ++j) {
for (int k = 0; k < 2; ++k) {
res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j]) % 10000;
}
}
}
return res;
}
mat matpow(mat x, ll n)
{
mat ans;
memset(ans.m, 0, sizeof(ans.m));
for (int i = 0; i < 2; ++i) ans.m[i][i] = 1;
for (; n; n >>= 1, x = mul(x, x))
if(n & 1) ans = mul(ans, x);
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
ll n;
while (cin >> n && n + 1){
t.m[0][0] = 1;
t.m[0][1] = 1;
t.m[1][0] = 1;
t.m[1][1] = 0;
tmp = matpow(t, n);
cout << tmp.m[0][1] << '\n';
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MOD = 10007;
struct mat
{
int m[5][5];
friend mat operator * (mat a, mat b) {
mat c;
memset(c.m, 0, sizeof(c.m));
for(int i = 0; i < 3; ++i) {
for(int j = 0; j < 3; ++j) {
for(int k = 0; k < 3; ++k) {
c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;
}
}
}
return c;
}
};
int solve(int t)
{
mat res, a;
a.m[0][0] = 2, a.m[0][1] = 1, a.m[0][2] = 0;
a.m[1][0] = 2, a.m[1][1] = 2, a.m[1][2] = 2;
a.m[2][0] = 0, a.m[2][1] = 1, a.m[2][2] = 2;
res = a;
while (t) {
if(t & 1) res = res * a;
a = a * a;
t >>= 1;
}
return res.m[0][0];
}
int main()
{
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
printf("%d\n", solve(n - 1));
}
return 0;
}