题意:给一个 n n n 行 m m m 列的方阵上色,只能上黑色或者白色,且必须满足左右相邻的格子颜色不能相同,问有多少种上色的方法。
思路:可以得出一行只有两种上色方法,而相邻两行之间互不影响,所以答案就是 2 n 2^n 2n 。
解法一:
由于
n
n
n 范围过大,可以通过欧拉降幂来减小时间复杂度。
欧拉降幂:
x
n
≡
x
n
m
o
d
φ
(
m
)
+
φ
(
m
)
(
m
o
d
m
)
x^n≡x^{n \ mod \ \varphi(m) \ + \ \varphi(m)} \ (mod \ m)
xn≡xn mod φ(m) + φ(m) (mod m)
由于
m
=
1
0
9
+
7
m = 10^9+7
m=109+7 ,所以
m
m
m 为质数,质数
m
m
m 的欧拉函数
φ
(
m
)
\varphi(m)
φ(m) 为
m
−
1
m-1
m−1。降幂后再通过快速幂即可求解。
#-*-coding:utf-8 -*-
n ,m = map(int ,input().split(" "))
p = 1000000007
n = n % (p - 1) + p - 1
a = [0]*12
b = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
len = -1
while n > 0:
len += 1
a[len] = n % 10
n = n // 10
ans = 1
for i in range(len):
ans = ans * b[a[len - i]] % p
ans = pow(ans ,10) % p
ans = ans * b[a[0]] % p
print(ans)
解法二:
因为是模数
m
m
m 是质数,所以也可以用费马小定理来进行降幂。
费马小定理:
a
p
−
1
≡
1
(
m
o
d
p
)
a^{p-1}≡1 \ (mod \ p)
ap−1≡1 (mod p) (
p
p
p 为质数)
代码同解法一是一样的
解法三:
c++直接用十进制快速幂
十进制快速幂:
设
n
=
∑
i
=
0
d
a
i
∗
1
0
i
n=\sum_{i=0}^{d}a_i*10^i
n=∑i=0dai∗10i
则
m
n
=
(
(
(
(
m
a
d
)
10
∗
m
a
d
−
1
)
10
∗
m
a
d
−
2
)
10
.
.
.
)
10
∗
m
a
0
m^n = ((((m^{a_d})^{10}*m^{a_{d-1}})^{10}*m^{a_{d-2}})^{10}...)^{10}*m^{a_0}
mn=((((mad)10∗mad−1)10∗mad−2)10...)10∗ma0
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const long long p = 1e9 + 7;
string a, b;
int num[10] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512};
long long ans, x;
int main()
{
cin >> a >> b;
ans = 1;
int len = a.size() - 1;
for (int i = 0; i < len; ++i)
{
(ans *= num[a[i] - '0']) %= p;
x = ans;
for (int j = 2; j <= 10; ++j)
(ans *= x) %= p;
}
(ans *= num[a[len] - '0']) %= p;
printf("%lld\n", ans);
return 0;
}