Codeforces-161-E(快速冪,)
阿新 • • 發佈:2018-12-21
Codeforces 161E-Tetrahedron
本篇文章部分參考於
題目原址
題意
一個正四面體頂點為A,B,C,D,從D出發,每走一步,更變當前所在頂點(不能保持不變),給定一個數 n ,求能有幾種不同路徑使得第 n 步走到 D。
題解
- 方法一(遞推)
分兩種情況: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] - 方法二(公式)()
有上述公式,就能用特徵方程解出 a[n] 表示式,對於任意的:有特徵方程可寫成:若其有解,則有:於是我們可以根據方法一中的表示式得出:於是再運用快速冪來求即可。還要尋找 4 的逆元,否則無法邊運算邊取模,很容易發現 是 4 在 mod 中的逆元。(因為 mod = 1e9+7) - 方法三(動態規劃)
用 dp[i][j] 表示第 i 步走到 j 點,則有:於是從遍歷i,j,k,最後取 dp[n][3] 即可 - 方法四(概率)
走 n 步的總共不同路徑有條,若算出第 n 點到達 D 的概率,最後乘上再取模即可。· 設為第 n 步到達 A 點的概率,那麼由對稱性可知:又知A,B,C三點完全等價,故有然後又可知第 n-1 步必定在A,B,C當中一點,且無論在哪一點總有的概率走到D,故有:結合可算出的表示式為:
實現1(遞推)
#include <stdio.h>
const int mod = (int)1e9 + 7;
const int maxn = (int)1e7 + 5;
long long a[maxn];
int main() {
int n;
scanf("%d", &n);
int i;
a[0] = 3;
a[1] = 6;
for (i = 2; i <= n-2; i++)
a[i] = (2 * a[i - 1] + 3 * a[i - 2])%mod;
printf("%I64d\n", a[n-2]);
}
實現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;
for (i = 2; i <= n; i++){
c = (2 * b + 3 * a)%mod;
a=b;
b=c;
}
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]);
}