hdu 1223 Order Count
http://acm.hdu.edu.cn/showproblem.php?pid=1223
dp递推求满足条件的不等式的个数。
这里需要用到大数乘法,于是我就顺便打了一个大数的模板,重载了+和*运算符。
递推的公式很简单,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j] * j,其中i 是指共有i 个符号,j 是指将i 个符号分成j 份,dp得到种类的数目。然后dp[i][1~i]各项相加,就是最终的答案了。
代码如下:
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cassert> 5 #include <cmath> 6 #include <algorithm> 7 8 using namespace std; 9 10 const int maxSize = 150; 11 12 struct bigNum { 13 char num[maxSize]; 14 }; 15 16 bigNum operator * (bigNum a, bigNum b) { 17 int la = strlen(a.num); 18 int lb = strlen(b.num); 19 bigNum ret; 20 int tmp[maxSize]; 21 22 for (int i = 0; i < la; i++) a.num[i] -= '0'; 23 for (int i = 0; i < lb; i++) b.num[i] -= '0'; 24 for (int i = 0, endi = la + lb; i <= endi; i++) tmp[i] = ret.num[i] = 0; 25 for (int i = 0; i < la; i++) { 26 int ti = la - 1 - i; 27 28 for (int j = 0; j < lb; j++) { 29 int tj = lb - 1 - j; 30 31 tmp[i + j] += a.num[ti] * b.num[tj]; 32 } 33 } 34 for (int i = 0, endi = la + lb - 1; i < endi; i++) { 35 tmp[i + 1] += tmp[i] / 10; 36 ret.num[endi - i] = tmp[i] % 10 + '0'; 37 } 38 ret.num[0] = tmp[la + lb - 2] / 10 + '0'; 39 40 if (ret.num[0] == '0') { 41 for (int i = 1, endi = la + lb + 2; i < endi; i++) { 42 ret.num[i - 1] = ret.num[i]; 43 } 44 } 45 46 return ret; 47 } 48 49 bigNum operator + (bigNum a, bigNum b) { 50 int la = strlen(a.num); 51 int lb = strlen(b.num); 52 bigNum ret; 53 int maxLen = max(la, lb); 54 int minLen = min(la, lb); 55 56 for (int i = 0; i <= maxLen + 1; i++) ret.num[i] = 0; 57 for (int i = 0; i < minLen; i++) { 58 ret.num[maxLen - i] += a.num[la - i - 1] + b.num[lb - i - 1] - '0'; 59 if (ret.num[maxLen - i] > '9') ret.num[maxLen - i - 1]++, ret.num[maxLen - i] -= 10; 60 } 61 if (maxLen == la) { 62 for (int i = minLen; i < maxLen; i++) { 63 ret.num[maxLen - i] += a.num[la - i - 1]; 64 if (ret.num[maxLen - i] > '9') ret.num[maxLen - i - 1]++, ret.num[maxLen - i] -= 10; 65 } 66 } else { 67 for (int i = minLen; i < maxLen; i++) { 68 ret.num[maxLen - i] += b.num[lb - i - 1]; 69 if (ret.num[maxLen - i] > '9') ret.num[maxLen - i - 1]++, ret.num[maxLen - i] -= 10; 70 } 71 } 72 ret.num[0] += '0'; 73 74 if (ret.num[0] == '0') { 75 for (int i = 1, endi = la + lb + 2; i < endi; i++) { 76 ret.num[i - 1] = ret.num[i]; 77 } 78 } 79 80 return ret; 81 82 } 83 84 const int maxn = 52; 85 bigNum dp[maxn][maxn]; 86 bigNum fac[maxn]; 87 88 char *con(int x) { 89 int len = (int)log10((double)x) + 1; 90 char *ret = new char[len + 1]; 91 92 for (int i = len - 1; i >= 0; i--) { 93 ret[i] = x % 10 + '0'; 94 x /= 10; 95 } 96 ret[len] = 0; 97 98 return ret; 99 } 100 101 void pre() { 102 strcpy(fac[0].num, "1"); 103 for (int i = 1; i < maxn; i++){ 104 bigNum tmp; 105 char *temp = con(i); 106 107 strcpy(tmp.num, temp); 108 delete temp; 109 fac[i] = fac[i - 1] * tmp; 110 } 111 for (int i = 1; i < maxn; i++) { 112 strcpy(dp[i][1].num, "1"); 113 strcpy(dp[i][i].num, "1"); 114 for (int j = 2; j < i; j++) { 115 bigNum tmp; 116 char *temp = con(j); 117 118 strcpy(tmp.num, temp); 119 delete temp; 120 dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j] * tmp; 121 } 122 strcpy(dp[i][0].num, "0"); 123 for (int j = 1; j <= i; j++){ 124 dp[i][0] = dp[i][0] + dp[i][j] * fac[j]; 125 } 126 //printf("%s\n", dp[i][0].num); 127 } 128 } 129 130 int main() { 131 pre(); 132 int n, T; 133 134 scanf("%d", &T); 135 while (T-- && ~scanf("%d", &n)){ 136 printf("%s\n", dp[n][0].num); 137 } 138 139 return 0; 140 }
——written by Lyon