문제 C. 모자 쓴 아이들
푸는데 0.3초밖에 안 걸린다. 추가로 sum of bar()도 dp로 바꿔버릴 수 있다. 사실 dp 테이블에서 삼각형 모양만 필요하니까 역삼각형 모양에 누적값을 저장해두는 식으로 활용하면 된다. 물론 dp[2001][2002]로 바꿔줘야 하지만... 그런데 이 문제에서는 그렇게 고친다고 엄청나게 빨라지지는 않는다. 그러므로 코드가 깔끔한 버전을 여기에 올림.
푸는데 0.3초밖에 안 걸린다. 추가로 sum of bar()도 dp로 바꿔버릴 수 있다. 사실 dp 테이블에서 삼각형 모양만 필요하니까 역삼각형 모양에 누적값을 저장해두는 식으로 활용하면 된다. 물론 dp[2001][2002]로 바꿔줘야 하지만... 그런데 이 문제에서는 그렇게 고친다고 엄청나게 빨라지지는 않는다. 그러므로 코드가 깔끔한 버전을 여기에 올림.
#include <stdio.h> #include <string.h> #include <assert.h> int dp[2001][2001]; void foo() { for (int i = 0; i <= 2000; ++i) { for (int j = 0; j <= i; ++j) { if (j > i / 2) { dp[i][j] = dp[i][i - j]; } else if (j == 0) { dp[i][j] = 1; } else { dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]; if (dp[i][j] >= 32749) dp[i][j] -= 32749; } } } } int bar(int i, int j) { if (i < 0 || i > 2000) { fprintf(stderr, "ERR_bar: %d\n", i); } if (j >= 0 && j <= i) return dp[i][j]; return 0; } int main(void) { foo(); int T_; scanf("%d", &T_); for (int i_ = 1; i_ <= T_; ++i_) { int B, W, k, i; scanf("%d %d %d %d", &B, &W, &k, &i); assert(k <= B + W); if (i > k) { fprintf(stderr, "ERR_INPUT: %d %d\n", i, k); } const int kk = (B + W) - k; int ans = bar(k - i, B - i + 1) // i는 흰색 + bar(k - i, W - i + 1); // i는 검은색 if (ans > 32749) ans -= 32749; if (ans) { int mul = 0; for (int m = i - 1 - kk; m <= i - 1; ++m) { mul += bar(i - 1, m); } mul %= 32749; for (int m = 1; m <= i - 1; ++m) { int x = 0; for (int p = 0; p <= kk; ++p) { x += bar(m - 1, p); } x %= 32749; mul -= bar(i - m - 1, kk - m + 1) * x; mul %= 32749; } //fprintf(stderr, "mul: %d\n", mul); ans *= mul; ans %= 32749; } printf("Case #%d: %d\n", i_, ans); } return 0; }