感覺全是思維亂搞題。
Gym - 101775J Straight Master
給你n種撲克,你每次可以出連續的3 ~ 5 張,問你能否出完。
Sample Input 2 13 1 2 2 1 0 0 0 0 0 0 0 0 0 13 1 1 1 1 0 1 1 0 0 0 0 0 0 Sample Output Case #1: Yes Case #2: No
相當於每次把一個長度為3~5的區間整體減1,問最后是否能夠全部減成0。
顯然,每次把一個長度大於5的區間整體減1也是可以的,因為6 = 3+3,7 = 3+4......
所以問題就變成了每次修改一個長度大於等於3的區間。
可以先維護原本序列的差分,然后區間整體減1就相當於a[l]--, a[r+1]++。
所以只要貪心的枚舉每個大於0的位置,然后找后面的離他最近的小於0的數字匹配,把前者減,后者加,就可以了。
如果最近的距離 < 3那么就是不可以。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; typedef long long LL; const int maxn = 200000 + 100; int a[maxn]; LL c[maxn]; int main() { int t; scanf("%d", &t); for (int ca = 1; ca <= t; ca++) { memset(a, 0, sizeof(a)); int n; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int i = 1; i <= n+1; i++) c[i] = a[i]-a[i-1]; bool flag = true; int r = 0; for (int i = 1; i <= n; i++) { while(c[i] > 0) { while(c[r] >= 0) if (++r > n+1) flag = false; if (r-i <= 2) flag = false; if (!flag) break; c[r] += c[i], c[i] = 0; if (c[r] > 0) c[i] = c[r], c[r] = 0; } if (!flag) break; } printf("Case #%d: %s\n", ca, flag?"Yes":"No"); } }
Gym - 101775L SOS
有一個長度為n的數組,Panda和Sheep輪流往一個空的位置上放 "S" 或者是 "O"。
如果有人放完后,構成一個連續的 "SOS",那么這個人就勝利。
現在是Panda先手,再兩個人足夠決策的情況下,誰會獲勝?
平局輸出"Draw"。
Sample Input 2 3 7 Sample Output Case #1: Draw Case #2: Panda
首先,可以看出一個必勝態一定存在一個S_ _S的情況。
如果構成了這個必勝態,n為奇數時先手勝,n為偶數時先手敗。
先討論n為奇數:
顯然的一點就是當n >= 7時,一定存在一個位置,先手放S可以構成一個必勝態,此時后手是無法阻止他的。
所以n為奇數且n >= 7時,先手是必勝的。
再討論n為偶數:
根據上面的結論,此時先手一定不想構成一個S_ _S的局面,所以第一步一定放O,來盡可能阻止后手構成此必勝態。
什么時候阻止不了呢?當放O的點左邊或右邊有至少8個點的時候。此時n為16。
綜上,n%2 == 1 && n >= 7,先手勝;n%2 == 0 && n >= 16,后手勝;否則就是平局。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; typedef long long LL; int main() { int n; scanf("%d", &n); for (int i = 1; i <= n; i++) { int t; scanf("%d", &t); if (t%2 == 1 && t >= 7) printf("Case #%d: Panda\n", i); else if (t%2 == 0 && t >= 16) printf("Case #%d: Sheep\n", i); else printf("Case #%d: Draw\n", i); } }