P1990-覆盖墙壁
分情況:
\[\left\{ \begin{aligned} & 條形 \left\{ \begin{aligned} 橫著\\ 豎著\\ \end{aligned}\right. \\ & L形\\ \end{aligned} \right. \]條形
設 $ F(n)$ 長度為 \(n\) 的方法數
橫著
\(F(n)+=F(n-1)\)
豎著
\(F(n)+=F(n-2)\)
L形
設\(G(n)\) 為長度凸出來那一點到 \(n\) 的方法數
\(G(n)=G(n-1)+F(n-2)\)
此為\(G\) 的遞推公式
答案
\(F(n)=F(n-1)+F(n-2)+2\times G(n-1)\)
此為\(F\) 的遞推公式
初始條件
\[F(0)=1\\ F(1)=1\\ F(2)=2\\\ \\ G(1)=0\\ G(2)=1\\ G(3)=1\\ G(4)=3\\ \]變式
\[\begin{aligned} &G(n)-G(n-1)=F(n-2)\\ &G(n-1)-G(n-2)=F(n-3)\\ &\cdots\\ &G(4)-G(3)=F(2)\\ &G(3)-G(2)=F(1)\\ &G(2)-G(1)=F(0)\\ &累加得\\ &G(n)=\sum_{k=0}^{n-2} F(k)+G(1)\\ &G(2)=1\\ &G(n)=\sum_{k=0}^{n-2} F(k)\\ \end{aligned} \]所以\(F(n)\) 得
\[\begin{aligned} &F(n)=F(n-1)+F(n-2)+2\times G(n-1)\\ &帶入G(n-1)\\ &得到F(n)=F(i-1)+F(i-2)+2\times\sum_{i=0}^{n-3} F(i)\\ \end{aligned} \]#include<iostream>
using namespace std;
const int N = 1e7+9;
int F[N];
int main() {
int n; cin >> n;
int ch = 0;
F[0] = 1; F[1] = 1; F[2] = 2;
for (int i = 3; i <= n; i++) {
ch += F[i - 3];
ch %= 10000;
F[i] = F[i - 1] + F[i - 2] + 2 * ch;
F[i] %= 10000;
}
cout << F[n];
return 0;
}
或者改為
#include<iostream>
using namespace std;
const int N = 1e7 + 9;
int F[N];
int main() {
int n; cin >> n;
int ch = 0;
F[3] = 1;\\表示n=0的時候
for (int i = 4; i <= n+3; i++) {
ch += F[i - 3];
ch %= 10000;
F[i] = F[i - 1] + F[i - 2] + 2 * ch;
F[i] %= 10000;
}
cout << F[n+3];
return 0;
}
由于只用到了\(F(i)\) \(F(i-1)\) \(F(i-2)\) \(F(3)\)
簡化為
#include<iostream>
using namespace std;
int main() {
int n; cin >> n;
int ch = 0;
int a = 0, b = 0, c = 1,ans=0;
for (int i = 1; i <= n; i++) {
ch += a;
ch %= 10000;
ans = b + c + 2 * ch;
ans %= 10000;
a = b;
b = c;
c = ans;
}
cout << ans;
return 0;
}
\(a\) 表示 \(F[-2]\)
\(b\) 表示 \(F[-1]\)
\(c\) 表示 \(F[0]\)
\(ans\) 表示 \(F[1]\)
分情況:
\[\left\{ \begin{aligned} & 條形 \left\{ \begin{aligned} 橫著\\ 豎著\\ \end{aligned}\right. \\ & L形\\ \end{aligned} \right. \]條形
設 $ F(n)$ 長度為 \(n\) 的方法數
橫著
\(F(n)+=F(n-1)\)
豎著
\(F(n)+=F(n-2)\)
L形
設\(G(n)\) 為長度凸出來那一點到 \(n\) 的方法數
\(G(n)=G(n-1)+F(n-2)\)
此為\(G\) 的遞推公式
答案
\(F(n)=F(n-1)+F(n-2)+2\times G(n-1)\)
此為\(F\) 的遞推公式
初始條件
\[F(0)=1\\ F(1)=1\\ F(2)=2\\\ \\ G(1)=0\\ G(2)=1\\ G(3)=1\\ G(4)=3\\ \]變式
\[\begin{aligned} &G(n)-G(n-1)=F(n-2)\\ &G(n-1)-G(n-2)=F(n-3)\\ &\cdots\\ &G(4)-G(3)=F(2)\\ &G(3)-G(2)=F(1)\\ &G(2)-G(1)=F(0)\\ &累加得\\ &G(n)=\sum_{k=0}^{n-2} F(k)+G(1)\\ &G(2)=1\\ &G(n)=\sum_{k=0}^{n-2} F(k)\\ \end{aligned} \]所以\(F(n)\) 得
\[\begin{aligned} &F(n)=F(n-1)+F(n-2)+2\times G(n-1)\\ &帶入G(n-1)\\ &得到F(n)=F(i-1)+F(i-2)+2\times\sum_{i=0}^{n-3} F(i)\\ \end{aligned} \]#include<iostream>
using namespace std;
const int N = 1e7+9;
int F[N];
int main() {
int n; cin >> n;
int ch = 0;
F[0] = 1; F[1] = 1; F[2] = 2;
for (int i = 3; i <= n; i++) {
ch += F[i - 3];
ch %= 10000;
F[i] = F[i - 1] + F[i - 2] + 2 * ch;
F[i] %= 10000;
}
cout << F[n];
return 0;
}
或者改為
#include<iostream>
using namespace std;
const int N = 1e7 + 9;
int F[N];
int main() {
int n; cin >> n;
int ch = 0;
F[3] = 1;\\表示n=0的時候
for (int i = 4; i <= n+3; i++) {
ch += F[i - 3];
ch %= 10000;
F[i] = F[i - 1] + F[i - 2] + 2 * ch;
F[i] %= 10000;
}
cout << F[n+3];
return 0;
}
由于只用到了\(F(i)\) \(F(i-1)\) \(F(i-2)\) \(F(3)\)
簡化為
#include<iostream>
using namespace std;
int main() {
int n; cin >> n;
int ch = 0;
int a = 0, b = 0, c = 1,ans=0;
for (int i = 1; i <= n; i++) {
ch += a;
ch %= 10000;
ans = b + c + 2 * ch;
ans %= 10000;
a = b;
b = c;
c = ans;
}
cout << ans;
return 0;
}
\(a\) 表示 \(F[-2]\)
\(b\) 表示 \(F[-1]\)
\(c\) 表示 \(F[0]\)
\(ans\) 表示 \(F[1]\)
總結
以上是生活随笔為你收集整理的P1990-覆盖墙壁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用推测解码 (Speculative
- 下一篇: 《优化接口设计的思路》系列:第七篇—接口