NC22669 舔狗舔到最后一无所有
[NC22669] 舔狗舔到最后一无所有
1 | 时间限制:C/C++ 1秒,其他语言2秒 |
题目描述
作为队伍的核心,forever97很受另外两个队友的尊敬。
Trote_w每天都要请forever97吃外卖,但很不幸的是宇宙中心forever97所在的学校周围只有3家forever97爱吃的外卖。
如果Trote_w给forever97买了别家的外卖,forever97就会大喊“我不吃我不吃”。
但是forever97又不喜欢连续三天吃一种外卖。
如果Trote_w哪天忘了这件事并且三天给他买了同一家外卖,那么forever97就会把Trote_w的头摁进手机屏幕里。
作为Trote_w的好朋友,你能告诉他连续请forever97吃n天饭,有多少不同的购买方法吗?
输入描述:
1 | 多组样例 |
输出描述:
1 | 输出T个整数代表方案数,由于答案太大,你只需要输出mod 1e9+7 后的答案即可。 |
输入
1 | 2 |
输出
1 | 24 |
题解:
状态转移方程:
f[0][i]表示第0家前i天购买总方案数
f[1][i]表示第1家前i天购买总方案数
f[2][i]表示第2家前i天购买总方案数
f[0][i]=f[1][i-1]+f[2][i-1]+f[0][i-1]
其意思为:第i天购买第0家的方案数=第i-1天购买第1家的方案数+第i-1天购买第0家的方案数(不能三个一样的,见下文)
f[0][i-1]=f[1][i-2]+f[2][i-2]+f[0][i-2]
这里把上面的f[0][i-1]拆开如下,但是如果f[0][i],f[0][i-1]都是买第0家的东西的话,那么如果再从f[0][i-2]购买第0家的东西的话,就会有三个一样的了,这样就不符合条件,那么就应该去掉f[0][i-2],然后化简式子为
f[0][i]=f[1][i-1]+f[2][i-1]+(f[1][i-2]+f[2][i-2])
同理可得其他两个的状态转移方程,在这里写出初态
f[0][1] = 1
1
0;
f[0][2] = 3
1
0,0;1,0;2,0;
我们发现f[0][i]=f[1][i]=f[2][i],那么可以得到到0,到1,到2的方案数和地推公式都是一样的,于是我们可以用一个一维数组在第i次的方案数的3倍来表示:
- dp[i]=f[0][i]+f[1][i]+f[2][i]=3f[0][i]=3f[1][i]=3f[2][i]
AC代码
1 |
|
吐槽
终于开dp了,半个月之后就ACM省赛了,有点忐忑= =