Codeforces 161E-Tetrahedron
本篇文章部分参考于
[https://blog.csdn.net/nolanddream/article/details/44086021]
题目原址
[http://codeforces.com/contest/166/problem/E]
题意
一个正四面体顶点为A,B,C,D,从D出发,每走一步,更变当前所在顶点(不能保持不变),给定一个数 n ,求能有几种不同路径使得第 n 步走到 D。
题解
- 方法一(递推)
O
(
n
)
O(n)
O(n)
分两种情况:1.第 n-2 步不在 D, 2.第 n-2 步在 D
设 a[n] 是第 n 步到达 D 的不同路径数。
· 对于 1 情况:第 n-2 步在A,B,C当中的一点,那么这时,在第 n-1 步能够到达 D,但其实他可以选择在第 n-1 到达另外两点,然后在第 n 步到达D,所以这种情况有 2a[n-1] 种。
· 对于 2 情况:第 n-2 步在D点,那么他可以通过走到A,B,C中的任意一点,再回到D点,所以这种情况有 3a[n-2] 种。
· 故有 a[n]=2a[n-1]+3a[n-2] - 方法二(公式)(
O
(
l
o
g
2
n
)
O(log_{2}{n})
O(log2n))
有上述公式,就能用特征方程解出 a[n] 表达式,对于任意的: A n = p A n − 1 + q A n − 2 A_{n}=pA_{n-1}+qA_{n-2} An=pAn−1+qAn−2有特征方程可写成: x 2 = p x + q x^{2}=px+q x2=px+q若其有解 x 1 , x 2 x_{1},x_{2} x1,x2,则有: A n = a x 1 n − 1 + b x 2 n − 1 A_{n}=ax_{1}^{n-1}+bx_{2}^{n-1} An=ax1n−1+bx2n−1于是我们可以根据方法一中的表达式得出: a n = 3 4 ( 3 n − 1 − ( − 1 ) n − 1 ) ( n > 1 ) a_{n}=\frac{3}{4}(3^{n-1}-(-1)^{n-1})~~(n>1) an=43(3n−1−(−1)n−1) (n>1)于是再运用快速幂来求 3 n − 1 3^{n-1} 3n−1即可。还要寻找 4 的逆元,否则无法边运算边取模,很容易发现 m o d + 1 4 \frac{mod+1}{4} 4mod+1 是 4 在 mod 中的逆元。(因为 mod = 1e9+7) - 方法三(动态规划)(
O
(
n
)
O(n)
O(n))
用 dp[i][j] 表示第 i 步走到 j 点,则有: d p [ i ] [ j ] = d p [ i ] [ j ] + d p [ i − 1 ] [ k ] ( j ≠ k ) dp[i][j]=dp[i][j]+dp[i-1][k]~~(j\ne{k}) dp[i][j]=dp[i][j]+dp[i−1][k] (j̸=k)于是从遍历i,j,k,最后取 dp[n][3] 即可 - 方法四(概率)
走 n 步的总共不同路径有 3 n 3^{n} 3n条,若算出第 n 点到达 D 的概率,最后乘上 3 n 3^{n} 3n再取模即可。· 设 P n ( A ) P_{n}(A) Pn(A)为第 n 步到达 A 点的概率,那么由对称性可知: P n ( A ) + P n ( B ) + P n ( C ) + P n ( D ) = 1 P_{n}(A)+P_{n}(B)+P_{n}(C)+P_{n}(D)=1 Pn(A)+Pn(B)+Pn(C)+Pn(D)=1又知A,B,C三点完全等价,故有 P n ( A ) = P n ( B ) = P n ( C ) = 1 − P n ( D ) 3 P_{n}(A)=P_{n}(B)=P_{n}(C)=\frac{1-P_{n}(D)}{3} Pn(A)=Pn(B)=Pn(C)=31−Pn(D)然后又可知第 n-1 步必定在A,B,C当中一点,且无论在哪一点总有 1 3 \frac{1}{3} 31的概率走到D,故有: P n + 1 ( D ) = 1 3 ( P n ( A ) + P n ( B ) + P n ( C ) ) = 1 − P n ( D ) 3 P_{n+1}(D)=\frac{1}{3}(P_{n}(A)+P_{n}(B)+P_{n}(C))=\frac{1-P_{n}(D)}{3} Pn+1(D)=31(Pn(A)+Pn(B)+Pn(C))=31−Pn(D)结合 P 1 ( D ) = 0 P_{1}(D)=0 P1(D)=0可算出 P n ( D ) P_{n}(D) Pn(D)的表达式为: 3 n P n ( D ) = 3 4 ( 3 n − 1 − ( − 1 ) n − 1 ) 3^{n}P_{n}(D)=\frac{3}{4}(3^{n-1}-(-1)^{n-1}) 3nPn(D)=43(3n−1−(−1)n−1)
实现1(递推)
#include <stdio.h>
const int mod = (int)1e9 + 7;
const int maxn = (int)1e7 + 5;
long long a[maxn] = {0,0,3};//a[1]=0,a[2]=3
int main() {
int n;
scanf("%d", &n);
int i;
for (i = 3; i <= n; i++)
a[i] = (2 * a[i - 1] + 3 * a[i - 2])%mod;
printf("%I64d\n", a[n]);
}
实现1`(递推,优化空间)
#include <stdio.h>
const int mod = (int)1e9 + 7;
const int maxn = (int)1e7 + 5;
int main() {
int n;
scanf("%d", &n);
int i;
long long a=1,b=0,c=0;//a[0]=1,a[1]=0
for (i = 2; i <= n; i++){
c = (2 * b + 3 * a)%mod;//计算a[n]
a=b;//更新a[n-2]
b=c;//更新a[n-1]
}
printf("%I64d\n", c);
}
实现2(公式,快速幂)
#include <stdio.h>
const int mod = (int)1e9 + 7;
const int inv4 = (mod + 1) / 4;//4的逆元
long long qpow(long long c, int n) {//快速幂
long long ans=1;
while (n > 0) {
if (n & 1)
ans =ans*c%mod;
c=c*c%mod;
n >>= 1;
}
return ans;
}
int solve(int n) {
long long ans;
if (n & 1)
ans = (3 * (qpow(3, n - 1) - 1))%mod * inv4 %mod;
else
ans = (3 * (qpow(3, n - 1) + 1))%mod * inv4 %mod;
return (int)ans;
}
int main() {
int n;
scanf("%d", &n);
printf("%d\n", solve(n));
}
实现3(动态规划)
#include <stdio.h>
const int mod = (int)1e9 + 7;
int d[(int)1e7+5][4];//0=A,1=B,2=C,3=D
int main() {
int n;
scanf("%d", &n);
d[1][0] = d[1][1] = d[1][2] = 1;
for (int i = 1; i <= n; i++)
for (int j = 0; j < 4; j++)
for (int k = 0; k < 4; k++)
if (j != k)//不能不动
d[i][j] = (d[i][j] + d[i - 1][k]) % mod;
printf("%d", d[n][3]);
}