2012 MUTC 6 总结
第五场组队赛了,这次的水题(题解叫签到题)过的很顺利,因为一点难度都没有,一眼就看出了做法,而全场就只出了那么两题....而我就只负责其中一题,和另外一题的做法。
这次多校联赛,刚开始了好几分钟,大board居然没有人过题,搞到都不知道哪题可以做了...不过其实1001就是水题,不过负责看那题的队友居然没发现,原因是看不懂题目.....- -!然后我看了题以后,发现是一个大水模拟题,于是今天打算再次鼓励队友,让他赶紧过了。结果,在打了几分钟以后,他居然搞出了个挺凌乱的代码,于是我在一旁就揪心了...最后不忍放过水题,再次一手抢过键盘敲了起来........不过,做的时候忽略了一些小问题,例如 模0 了,于是我就意外的RE了一次T^T!改过来以后就AC了~
在我打上面这题的时候,我顺便看了一下1006,想了一下就想到是三分了...不过其实那时我没想清楚怎么证明是三分,赛后才跟大牛交流的时候才发觉,原来证明起来好像挺麻烦的..- - 不过幸亏当时没考虑太多,才能以最快的速度告诉队友这个的做法,然后在他敲三分的时候我就上了个厕所了~ 回来以后,真的AC了.....
然后就是1008,一道挺有技巧的题,不过当时还真的没发现奇偶性的规律,所以没有做出....
其实后面的三个多钟,我们一直在讨论1010,因为觉的这个递推是可以做的.....终于,在只剩一个钟的时候,把思路理清了,代码也写了个记忆化dfs,可惜的是,这样做会超时,而且是一定会超的......然后,我们居然花了半多个钟才把它改成dp,这是何等低的代码速度....囧!
按照思路改了dp后,测试的时候发现,预处理的时间是多么的漫长,于是我们在仅余的十来分钟里对它进行剪枝....不过最后两三分钟才发现要记忆化dp的部分过程,随后来不及改了,所以带着遗憾结束了比赛.....
看了题解,题解对我们合作讨论出来的那题贴上了简单题的标签...................于是我就觉得,我真的应该尽快看懂,搞熟练递推类的题目!不能让这种“简单题”挡住我前进的步伐的!!!
更新:添加1010的代码 hdu 3459
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cmath> 6 using namespace std; 7 8 #define debug 0 9 10 typedef __int64 ll; 11 12 const ll mod = 1000000007; 13 const int maxn = 365; 14 ll dp[maxn][maxn], ss[maxn][maxn]; // ss用于储存前k项和 15 ll cc[maxn][maxn]; // cc用于储存组合数 16 int lg[maxn]; 17 18 int min2(int a, int b){return a < b ? a : b;} 19 int max2(int a, int b){return a > b ? a : b;} 20 21 void get_c(){ // 用杨辉三角递推上去 22 memset(cc, 0, sizeof(cc)); 23 memset(ss, 0, sizeof(ss)); 24 cc[0][0] = cc[1][0] = cc[1][1] = 1; 25 for (int i = 2; i < maxn; i++){ 26 cc[i][0] = 1; 27 for (int j = 1; j <= i; j++){ 28 cc[i][j] = (cc[i - 1][j] + cc[i - 1][j - 1]) % mod; 29 } 30 } 31 //printf("%I64d %I64d\n", cc[4][2], cc[5][2]); 32 } 33 34 void init(){ 35 lg[0] = 0; 36 for (int i = 1; i < maxn; i++){ 37 lg[i] = (int)floor(log10((double)i) / log10((double)2)) + 1; 38 } 39 memset(dp, 0, sizeof(dp)); 40 ss[0][0] = dp[0][0] = 1; 41 dp[1][1] = 1; 42 dp[2][2] = 4; 43 for (int i = 1; i < maxn; i++){ 44 ss[0][i] = ss[1][i] = 1; 45 ss[2][i] = 4; 46 } 47 ss[2][1] = 0; 48 } 49 50 ll perm(int a){ 51 ll ret = 1; 52 53 for (ll i = 2; i <= a; i++){ 54 ret *= i; 55 ret %= mod; 56 } 57 58 return ret; 59 } 60 61 void pre(){ 62 ll tmp1, tmp2; 63 64 for (int n = 3; n <= 360; n++){ 65 for (int k = lg[n]; k <= n; k++){ 66 for (int i = 0; i <= n - 1; i++){ 67 tmp1 = tmp2 = 0; 68 if (dp[n - i - 1][k - 1]){ 69 if (lg[i]) tmp1 = ss[i][min2(k - 2, i)] - ss[i][lg[i] - 1]; 70 else tmp1 = ss[i][min2(k - 2, i)]; 71 tmp1 %= mod; 72 tmp1 *= dp[n - i - 1][k - 1]; 73 tmp1 %= mod; 74 } // 枚举右子树满的情况 75 if (dp[i][k - 1]){ 76 if (lg[n - i - 1]) tmp2 = ss[n - i - 1][min2(k - 2, n - i - 1)] - ss[n - i - 1][lg[n - i - 1] - 1]; 77 else tmp2 = ss[n - i - 1][min2(k - 2, n - i - 1)]; 78 tmp2 %= mod; 79 tmp2 *= dp[i][k - 1]; 80 tmp2 %= mod; 81 } // 枚举左子树满的情况 82 if (i != n - 1){ 83 dp[n][k] += (((tmp1 + tmp2) % mod) * cc[n - 2][i]) % mod + (((dp[i][k - 1] * dp[n - i - 1][k - 1]) % mod) * cc[n - 2][i]) % mod; 84 dp[n][k] %= mod; 85 } 86 else{ 87 dp[n][k] += ((tmp1 + tmp2) % mod) + (((dp[i][k - 1] * dp[n - i - 1][k - 1]) % mod) * cc[n - 2][i]) % mod; 88 dp[n][k] %= mod; 89 } 90 } 91 dp[n][k] *= n; 92 dp[n][k] %= mod; 93 ss[n][k] = ss[n][k - 1] + dp[n][k]; 94 } 95 for (int k = n + 1; k <= 360; k++){ 96 ss[n][k] = ss[n][k - 1]; 97 } 98 } 99 #if debug 100 for (int i = 0; i < 10; i++){ 101 for (int j = 0; j < 10; j++) 102 printf("%6I64d ", dp[i][j]); 103 puts(""); 104 } 105 for (int i = 0; i < 10; i++){ 106 for (int j = 0; j < 10; j++) 107 printf("%6I64d ", ss[i][j]); 108 puts(""); 109 } 110 #endif 111 } 112 /* 113 ll dfs(int n, int k){ 114 ll ret = 0; 115 ll tmp1, tmp2; 116 117 if (dp[n][k]) return dp[n][k]; 118 if (!n || k < lg[n] || k > n) return 0; 119 120 for (int i = 0; i <= n - 1; i++){ 121 #if debug 122 printf("i %d:\n", i); 123 #endif 124 tmp1 = tmp2 = 0; 125 for (int j = lg[i]; j <= min2(k - 2, i); j++){ 126 tmp1 += dfs(i, j); 127 tmp1 %= mod; 128 129 //ret += ((dfs(i, j) * dfs(n - i - 1, k - 1)) % mod) * C(n - 2, i); 130 //ret %= mod; 131 } 132 #if debug 133 printf("%d %d tmp1: %I64d %d %d r: %I64d\n", n, k, tmp1, n - i - 1, k - 1, dfs(n - i - 1, k - 1)); 134 #endif 135 tmp1 *= dfs(n - i - 1, k - 1); 136 tmp1 %= mod; 137 for (int j = lg[n - i - 1]; j <= min2(k - 2, n - i - 1); j++){ 138 tmp2 += dfs(n - i - 1, j); 139 tmp2 %= mod; 140 141 //ret += ((dfs(i, k - 1) * dfs(n - i - 1, j)) % mod) * C(n - 2, i); 142 //ret %= mod; 143 } 144 #if debug 145 printf("%d %d tmp2: %I64d %d %d l: %I64d\n", n, k, tmp2, i, k - 1, dfs(i, k - 1)); 146 #endif 147 tmp2 *= dfs(i, k - 1); 148 tmp2 %= mod; 149 #if debug 150 printf("tmp1 %I64d tmp2 %I64d C %I64d\n", tmp1, tmp2, C(n - 2, i)); 151 #endif 152 if (i != n - 1){ 153 ret += (((tmp1 + tmp2) % mod) * cc[n - 2][i]) % mod + (((dfs(i, k - 1) * dfs(n - i - 1, k - 1)) % mod) * cc[n - 2][i]) % mod; 154 ret %= mod; 155 } 156 else{ 157 ret += ((tmp1 + tmp2) % mod) % mod + (((dfs(i, k - 1) * dfs(n - i - 1, k - 1)) % mod) * cc[n - 2][i]) % mod; 158 ret %= mod; 159 } 160 #if debug 161 printf("%d %d add: %I64d ret: %I64d \n", n, k, dfs(i, k - 1) * dfs(n - i - 1, k - 1) * C(n - 2, i), ret); 162 #endif 163 164 } 165 ret *= n; 166 ret %= mod; 167 dp[n][k] = ret; 168 #if debug 169 printf("%d %d : %I64d\n", n, k, ret); 170 #endif 171 172 return ret; 173 } 174 */ 175 int main(){ 176 int a, b; 177 int i = 1, c; 178 179 get_c(); 180 init(); 181 pre(); 182 //puts("pass"); 183 184 185 scanf("%d", &c); 186 while (c-- && ~scanf("%d%d", &a, &b)){ 187 printf("Case #%d: %I64d\n", i, dp[a][b]); 188 i++; 189 } 190 191 return 0; 192 }
添加1008的代码 hdu 3457
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 4 void chg(char &a, char &b){ 5 char t = a; 6 7 a = b + 1; 8 if (a > 'z') a -= 26; 9 b = t + 1; 10 if (b > 'z') b -= 26; 11 } 12 13 bool judge(char *a, char *b){ 14 int l = strlen(a); 15 int sum = 0; 16 17 if (l == 2){ 18 for (int i = 0; i < 26; i++){ 19 chg(a[0], a[1]); 20 if (!strcmp(a, b)) return true; 21 } 22 return false; 23 } 24 for (int i = 0; i < l; i++){ 25 sum += a[i] - b[i]; 26 } 27 if (sum & 1) return false; 28 return true; 29 } 30 31 int main(){ 32 char s1[100], s2[100]; 33 int n; 34 35 scanf("%d", &n); 36 for (int tt = 1; tt <= n; tt++){ 37 scanf("%s%s", s1, s2); 38 printf("Case #%d: ", tt); 39 if (judge(s1, s2)) printf("YES\n"); 40 else printf("NO\n"); 41 } 42 43 return 0; 44 }
——written by Lyon