Description
小L热衷于undercards. 在undercards中,有四个格子。每个格子要么是空的,要么住着一只BigBob。每个BigBob有一个不超过k的血量;血量减到0视为死亡。那个格子随即空出。 当一只BigBob受到伤害后,假如它没有死亡且剩余血量为t,它会从左数第一个空格处召唤一只血量为a[t]的BigBob;若没有空格,则不会召唤。
法术R定义为:从左往右,对每个BigBob造成一点伤害;假如有BigBob死亡,重复上述效果。
聪明的小L发现,在某些情况下,当他发动法术R时,游戏会陷入循环。
他想求出这样的初始情形有多少种。
Input
输入一个正整数k;
随后一行k-1个正整数,表示a[1]~a[k-1];
Output
输出一个整数,表示答案。
2 2
Sample Input
31
Sample Output
HINT
【样例解释】
Bigbob最多有2血,满血bigbob受伤会召出新的。
循环的初始状态有:
(2,1,0,0),(1,2,0,0),(2,0,1,0),(2,1,1,0),(0,2,1,0),(1,2,1,0),(2,2,1,0) ,(1,0,2,0),(
0,1,2,0),(1,1,2,0),(2,1,2,0),(2,1,0,1),(0,2,0,1),(1,2,0,1),(0,2,1,1),(1,2,1,1),(0,0,2,
1),(1,0,2,1),(0,1,2,1),(1,1,2,1),(2,1,2,1),(0,2,2,1),(1,2,2,1),(2,1,0,2) ,(1,2,0,2),(2,
0,1,2),(2,1,1,2),(0,2,1,2),(1,2,1,2),(2,2,1,2),(2,1,2,2)
共31种。
【数据范围】
对于30%的数据,k≤5;
对于70%的数据,k≤10, a[i]=k;
对于100%的数据,k≤15, 1≤a[i]≤k。
Source/Category
2019年海淀区挑战赛初中组
直接模拟+判环
#include
#include
using namespace std;
const int MAXN = 16*16*16*16+10;
int k, t[MAXN], nxt[MAXN], flag[MAXN]; bool vis[MAXN];
int f(int a, int b, int c, int d) {
int kk = k+1;
return a*kk*kk*kk+b*kk*kk+c*kk+d;
}
int g(int a, int b, int c, int d) { // 模拟
bool flag = false;
if (a) {
if (--a) {
if (!b) b=t[a];
else if (!c) c=t[a];
else if (!d) d=t[a];
}
else flag=true;
}
if (b) {
if (--b) {
if (!a) a=t[b];
else if (!c) c=t[b];
else if (!d) d=t[b];
}
else flag=true;
}
if (c) {
if (--c) {
if (!a) a=t[c];
else if (!b) b=t[c];
else if (!d) d=t[c];
}
else flag=true;
}
if (d) {
if (--d) {
if (!a) a=t[d];
else if (!b) b=t[d];
else if (!c) c=t[d];
}
else flag=true;
}
if (!flag) return -1; // 要是没死人,你就没得走了
else return f(a,b,c,d);
}
void dfs(int u) { // 判环
if (vis[u]) return;
vis[u] = true;
if (nxt[u]==-1) { // 到达结尾,没有
flag[u]=2; return;
}
dfs(nxt[u]);
if (flag[nxt[u]]==2) flag[u]=2; // 如果下面的不通,这里不通否则通
else flag[u]=1;
}
int main() {
scanf("%d", &k);
for (int i=1; i