NC20875 舔狗舔到最后一无所有
题目
题目描述
作为队伍的核心,forever97很受另外两个队友的尊敬。
Trote_w每天都要请forever97吃外卖,但很不幸的是宇宙中心forever97所在的学校周围只有3家forever97爱吃的外卖。
如果Trote_w给forever97买了别家的外卖,forever97就会大喊“我不吃我不吃”。
但是forever97又不喜欢连续三天吃一种外卖。
如果Trote_w哪天忘了这件事并且三天给他买了同一家外卖,那么forever97就会把Trote_w的头摁进手机屏幕里。
作为Trote_w的好朋友,你能告诉他连续请forever97吃n天饭,有多少不同的购买方法吗?
输入描述
多组样例
第一行一个整数T(1<=T<=20)代表测试样例数
接下来t行每行一个整数n,代表Trote_w要请forever97吃n天饭(1<=n<=100000)
输出描述
输出T个整数代表方案数,由于答案太大,你只需要输出mod 1e9+7 后的答案即可。
示例1
输入
2
3
500
输出
24
544984352
题解
知识点:线性dp。
显然是个递推的题,但转移方程稍微有点难想。
考虑 \(dp[i]\) 是第 \(i\) 天的方案数,则第 \(i\) 天可以由 \(i-2\) 天方案再买两次一样但和 \(i-2\) 天不一样的外卖或者 \(i-1\) 天再买一次与 \(i-1\) 天不一样的外卖,因此有转移方程:\(dp[i] = 2(dp[i-1]+dp[i-2])\) 。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod = 1e9 + 7;
int dp[100007];
bool solve() {
int n;
cin >> n;
dp[1] = 3;
dp[2] = 9;
for (int i = 3;i <= n;i++) dp[i] = 2LL * (dp[i - 1] + dp[i - 2]) % mod;
cout << dp[n] << '\n';
return true;
}
///i-2往后两天一样,但和i-2不一样,2*dp[i-2]
///i-1往后一天,和i-1不一样,2*dp[i-1]
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16559036.html