HDU 4602 Partition

f[i]表示和为i的方案数。已知f[i]=2i-1

dp[i]表示和为i,k有多少个。那么dp[i]=dp[1]+dp[2]+...+dp[i-1]+f[i-k]。

考虑与f有关的项:

f[n-k]是答案的一部分,即2n-k-1是答案的一部分。

把与dp有关的项:

令s[i-1]=dp[1]+dp[2]+...+dp[i-1],那么s[n-1]是答案的一部分。

s[i]=s[i-1]+dp[i],又dp[i]=s[i-1]+f[i-k]。推出s[i]=2*s[i-1]+f[i-k],dp[k]=s[k]=1。

可以推出s[n-1]=2n-k-1+(n-k-1)*2n-k-2

  1. #include<iostream>
  2. typedef long long LL;
  3. LL MOD = 1000000007LL;
  4. using namespace std;
  5. LL powmod(LL a, LL b) {
  6. LL ans;
  7. a %= MOD;
  8. for (ans = ; b; b >>= ) {
  9. if (b & ) {
  10. ans *= a;
  11. ans %= MOD;
  12. }
  13. a *= a;
  14. a %= MOD;
  15. }
  16. return ans;
  17. }
  18. int main() {
  19. int T;
  20. LL n, k;
  21. LL ans;
  22. cin >> T;
  23. while (T--) {
  24. cin >> n >> k;
  25. if (k > n) {
  26. ans = ;
  27. } else if (k == n) {
  28. ans = ;
  29. } else if (n - k == ) {
  30. ans = ;
  31. } else if (n - k == ) {
  32. ans = ;
  33. } else {
  34. ans = powmod(, n - k - )
  35. + (n - k - ) * powmod(, n - k - ) % MOD;
  36. ans += powmod(, n - k - );
  37. ans = (ans % MOD + MOD) % MOD;
  38. }
  39. cout << ans << endl;
  40. }
  41. return ;
  42. }

HDU 4604 Deque

枚举第i个数,假设它最早出现且在队列里,那么以i为起点的最长非降子序列一定在队列里(push_back),以i为起点的最长非升子序列也一定在队列里(push_front)。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #define MAXN 100010
  4. #define oo 123456789
  5. using namespace std;
  6. int arr[MAXN];
  7. int up[MAXN], down[MAXN], cnt[MAXN];
  8. int st[MAXN], top;
  9. void LIS(int n, int dp[]) {
  10. int i;
  11. int pos;
  12. top = -;
  13. for (i = ; i < n; i++) {
  14. if (top < || st[top] <= arr[i]) {
  15. st[++top] = arr[i];
  16. dp[i] = top + ;
  17. } else {
  18. pos = upper_bound(st, st + top + , arr[i]) - st;
  19. st[pos] = arr[i];
  20. dp[i] = pos + ;
  21. }
  22. cnt[i] = min(cnt[i],
  23. upper_bound(st, st + top + , arr[i])
  24. - lower_bound(st, st + top + , arr[i]));
  25. }
  26. }
  27. int main() {
  28. int T;
  29. int n;
  30. int i;
  31. int ans;
  32. scanf("%d", &T);
  33. while (T--) {
  34. scanf("%d", &n);
  35. for (i = ; i < n; i++) {
  36. scanf("%d", &arr[i]);
  37. cnt[i] = oo;
  38. }
  39. reverse(arr, arr + n);
  40. LIS(n, up);
  41. for (i = ; i < n; i++) {
  42. arr[i] = -arr[i];
  43. }
  44. LIS(n, down);
  45. ans = ;
  46. for (i = ; i < n; i++) {
  47. ans = max(ans, up[i] + down[i] - cnt[i]);
  48. }
  49. printf("%d\n", ans);
  50. }
  51. return ;
  52. }

HDU 4605 Magic Ball Game

统计树上一个节点到根,权值大于/小于某个数的个数:数状数组/线段树。

离线处理询问,对所有w的值离散化。

从树根开始DFS,第一次到达一个节点时,回答所有询问。

向儿子DFS时,更新往左/右的数状数组。

最后一次离开一个节点时,还原现场。

  1. #pragma comment(linker, "/STACK:1024000000,1024000000")
  2.  
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<vector>
  7. #include<set>
  8. #define MAXN 200010
  9. using namespace std;
  10. int w[MAXN], tmp[MAXN];
  11. struct node {
  12. int pre;
  13. int next[];
  14. void init() {
  15. pre = -;
  16. next[] = next[] = -;
  17. }
  18. } tree[MAXN];
  19. struct Ask {
  20. int weight;
  21. int pos;
  22. };
  23. vector<Ask> q[MAXN];
  24. pair<int, int> res[MAXN];
  25. bool stop[MAXN];
  26. multiset<int> myset;
  27. inline int lowbit(int x) {
  28. return x & -x;
  29. }
  30. void update(int arr[], int i, int val) {
  31. for (; i < MAXN; i += lowbit(i)) {
  32. arr[i] += val;
  33. }
  34. }
  35. int sum(int arr[], int i) {
  36. int ans;
  37. for (ans = ; i > ; i -= lowbit(i)) {
  38. ans += arr[i];
  39. }
  40. return ans;
  41. }
  42. int left[MAXN], right[MAXN];
  43. void dfs(int x) {
  44. int i, j;
  45. for (i = ; i < (int) q[x].size(); i++) {
  46. j = q[x][i].pos;
  47. if (myset.count(q[x][i].weight)) {
  48. res[j].first = -;
  49. } else {
  50. res[j].first = sum(right, q[x][i].weight - );
  51. res[j].second = * sum(left, q[x][i].weight - )
  52. + * sum(right, q[x][i].weight - );
  53.  
  54. res[j].second += sum(left, MAXN - ) - sum(left, q[x][i].weight);
  55. res[j].second += sum(right, MAXN - ) - sum(right, q[x][i].weight);
  56. }
  57. }
  58.  
  59. myset.insert(w[x]);
  60. if (tree[x].next[] != -) {
  61. update(left, w[x], );
  62. dfs(tree[x].next[]);
  63. update(left, w[x], -);
  64. }
  65. if (tree[x].next[] != -) {
  66. update(right, w[x], );
  67. dfs(tree[x].next[]);
  68. update(right, w[x], -);
  69. }
  70. myset.erase(myset.find(w[x]));
  71. }
  72. int main() {
  73. int T;
  74. int n, m;
  75. int i, j;
  76. int u, a, b;
  77. int size;
  78. Ask ask;
  79. scanf("%d", &T);
  80. while (T--) {
  81. scanf("%d", &n);
  82. size = ;
  83. for (i = ; i <= n; i++) {
  84. scanf("%d", &w[i]);
  85. tree[i].init();
  86. q[i].clear();
  87. tmp[size++] = w[i];
  88. }
  89. scanf("%d", &m);
  90. while (m--) {
  91. scanf("%d%d%d", &u, &a, &b);
  92. tree[u].next[] = a;
  93. tree[u].next[] = b;
  94. tree[a].pre = u;
  95. tree[b].pre = u;
  96. }
  97. scanf("%d", &m);
  98. for (i = ; i < m; i++) {
  99. scanf("%d%d", &u, &ask.weight);
  100. ask.pos = i;
  101. q[u].push_back(ask);
  102. tmp[size++] = ask.weight;
  103. }
  104. sort(tmp, tmp + size);
  105. size = unique(tmp, tmp + size) - tmp;
  106. for (i = ; i <= n; i++) {
  107. w[i] = lower_bound(tmp, tmp + size, w[i]) - tmp + ;
  108. for (j = ; j < (int) q[i].size(); j++) {
  109. q[i][j].weight = lower_bound(tmp, tmp + size, q[i][j].weight)
  110. - tmp + ;
  111. }
  112. }
  113. myset.clear();
  114. memset(left, , sizeof(left));
  115. memset(right, , sizeof(right));
  116. for (i = ; i <= n; i++) {
  117. if (tree[i].pre < ) {
  118. dfs(i);
  119. break;
  120. }
  121. }
  122. for (i = ; i < m; i++) {
  123. if (res[i].first < ) {
  124. puts("");
  125. } else {
  126. printf("%d %d\n", res[i].first, res[i].second);
  127. }
  128. }
  129. }
  130. return ;
  131. }

HDU 4606 Occupy Cities

预处理出任意两个城市的最短距离。

若士兵可以从一个城市i到达另一个城市j,且i比j先占领,才连i->j的边。

二分士兵背包的容量,可以得到一个有向图。二分条件是有向图的最小路径覆盖与士兵人数的关系。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cmath>
  5. #define MAXN 310
  6. #define MAXM 10010
  7. #define oo 123456789
  8. #define eps 1e-6
  9. using namespace std;
  10.  
  11. struct point {
  12. double x, y;
  13. };
  14. struct line {
  15. point a, b;
  16. };
  17. point city[MAXN];
  18. line barr[MAXN];
  19.  
  20. double dis[MAXN][MAXN];
  21. int first[MAXM], next[MAXM], v[MAXM], e;
  22. int order[MAXN];
  23. int cx[MAXN], cy[MAXN];
  24. bool mk[MAXN];
  25.  
  26. int dbcmp(double x, double y) {
  27. if (fabs(x - y) < eps) {
  28. return ;
  29. } else {
  30. return x > y ? : -;
  31. }
  32. }
  33. bool zero(double x) {
  34. return fabs(x) < eps;
  35. }
  36. double dist(point p1, point p2) {
  37. return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
  38. }
  39. double xmult(point p1, point p2, point p0) {
  40. return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
  41. }
  42. int dots_inline(point p1, point p2, point p3) {
  43. return zero(xmult(p1, p2, p3));
  44. }
  45. int same_side(point p1, point p2, line l) {
  46. return xmult(l.a, p1, l.b) * xmult(l.a, p2, l.b) > eps;
  47. }
  48. int same_side(point p1, point p2, point l1, point l2) {
  49. return xmult(l1, p1, l2) * xmult(l1, p2, l2) > eps;
  50. }
  51. inline int dot_online_in(point p, point l1, point l2) {
  52. return zero(xmult(p, l1, l2)) && (l1.x - p.x) * (l2.x - p.x) < eps
  53. && (l1.y - p.y) * (l2.y - p.y) < eps;
  54. }
  55. int dot_online_in(point p, line l) {
  56. return zero(xmult(p, l.a, l.b)) && (l.a.x - p.x) * (l.b.x - p.x) < eps
  57. && (l.a.y - p.y) * (l.b.y - p.y) < eps;
  58. }
  59. int intersect_in(point u1, point u2, point v1, point v2) {
  60. if (!dots_inline(u1, u2, v1) || !dots_inline(u1, u2, v2))
  61. return !same_side(u1, u2, v1, v2) && !same_side(v1, v2, u1, u2);
  62. return dot_online_in(u1, v1, v2) || dot_online_in(u2, v1, v2)
  63. || dot_online_in(v1, u1, u2) || dot_online_in(v2, u1, u2);
  64. }
  65.  
  66. void floyd(int n) {
  67. int i, j, k;
  68. for (k = ; k < n; k++) {
  69. for (i = ; i < n; i++) {
  70. for (j = ; j < n; j++) {
  71. dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
  72. }
  73. }
  74. }
  75. }
  76. inline void addEdge(int x, int y) {
  77. v[e] = y;
  78. next[e] = first[x];
  79. first[x] = e++;
  80. }
  81. int path(int x) {
  82. int y;
  83. for (int i = first[x]; i != -; i = next[i]) {
  84. y = v[i];
  85. if (!mk[y]) {
  86. mk[y] = true;
  87. if (cy[y] == - || path(cy[y])) {
  88. cx[x] = y;
  89. cy[y] = x;
  90. return ;
  91. }
  92. }
  93. }
  94. return ;
  95. }
  96. int match(int n) {
  97. int res, i;
  98. memset(cx, -, sizeof(cx));
  99. memset(cy, -, sizeof(cy));
  100. for (res = i = ; i < n; i++) {
  101. if (cx[i] == -) {
  102. memset(mk, false, sizeof(mk));
  103. res += path(i);
  104. }
  105. }
  106. return res;
  107. }
  108. int main() {
  109. int T;
  110. int n, m, p;
  111. int i, j, k;
  112. double low, high, mid;
  113. scanf("%d", &T);
  114. while (T--) {
  115. scanf("%d%d%d", &n, &m, &p);
  116. for (i = ; i < n; i++) {
  117. scanf("%lf%lf", &city[i].x, &city[i].y);
  118. }
  119. for (i = ; i < m; i++) {
  120. scanf("%lf%lf%lf%lf", &barr[i].a.x, &barr[i].a.y, &barr[i].b.x,
  121. &barr[i].b.y);
  122. }
  123. for (i = ; i < n; i++) {
  124. scanf("%d", &order[i]);
  125. order[i]--;
  126. }
  127.  
  128. for (i = ; i < n + m + m; i++) {
  129. for (j = ; j <= i; j++) {
  130. dis[i][j] = dis[j][i] = oo;
  131. }
  132. }
  133.  
  134. for (i = ; i < n; i++) {
  135. dis[i][i] = ;
  136. for (j = i + ; j < n; j++) {
  137. for (k = ; k < m; k++) {
  138. if (intersect_in(city[i], city[j], barr[k].a, barr[k].b)) {
  139. break;
  140. }
  141. }
  142. if (k >= m) {
  143. dis[i][j] = dis[j][i] = dist(city[i], city[j]);
  144. }
  145. }
  146. }
  147.  
  148. for (i = ; i < n; i++) {
  149. for (j = ; j < m; j++) {
  150. for (k = ; k < m; k++) {
  151. if (j == k) {
  152. continue;
  153. }
  154. if (intersect_in(city[i], barr[j].a, barr[k].a,
  155. barr[k].b)) {
  156. break;
  157. }
  158. }
  159. if (k >= m) {
  160. dis[i][n + (j << )] = dis[n + (j << )][i] = dist(city[i],
  161. barr[j].a);
  162. }
  163. for (k = ; k < m; k++) {
  164. if (j == k) {
  165. continue;
  166. }
  167. if (intersect_in(city[i], barr[j].b, barr[k].a,
  168. barr[k].b)) {
  169. break;
  170. }
  171. }
  172. if (k >= m) {
  173. dis[i][n + (j << | )] = dis[n + (j << | )][i] = dist(
  174. city[i], barr[j].b);
  175. }
  176.  
  177. }
  178. }
  179.  
  180. for (i = ; i < m; i++) {
  181. for (j = ; j < i; j++) {
  182. for (k = ; k < m; k++) {
  183. if (k == i || k == j) {
  184. continue;
  185. }
  186. if (intersect_in(barr[i].a, barr[j].a, barr[k].a,
  187. barr[k].b)) {
  188. break;
  189. }
  190. }
  191. if (k >= m) {
  192. dis[n + (i << )][n + (j << )] = dis[n + (j << )][n
  193. + (i << )] = dist(barr[i].a, barr[j].a);
  194. }
  195.  
  196. for (k = ; k < m; k++) {
  197. if (k == i || k == j) {
  198. continue;
  199. }
  200. if (intersect_in(barr[i].a, barr[j].b, barr[k].a,
  201. barr[k].b)) {
  202. break;
  203. }
  204. }
  205. if (k >= m) {
  206. dis[n + (i << )][n + (j << | )] =
  207. dis[n + (j << | )][n + (i << )] = dist(
  208. barr[i].a, barr[j].b);
  209. }
  210.  
  211. for (k = ; k < m; k++) {
  212. if (k == i || k == j) {
  213. continue;
  214. }
  215. if (intersect_in(barr[i].b, barr[j].a, barr[k].a,
  216. barr[k].b)) {
  217. break;
  218. }
  219. }
  220. if (k >= m) {
  221. dis[n + (i << | )][n + (j << )] = dis[n + (j << )][n
  222. + (i << | )] = dist(barr[i].b, barr[j].a);
  223. }
  224.  
  225. for (k = ; k < m; k++) {
  226. if (k == i || k == j) {
  227. continue;
  228. }
  229. if (intersect_in(barr[i].b, barr[j].b, barr[k].a,
  230. barr[k].b)) {
  231. break;
  232. }
  233. }
  234. if (k >= m) {
  235. dis[n + (i << | )][n + (j << | )] = dis[n
  236. + (j << | )][n + (i << | )] = dist(barr[i].b,
  237. barr[j].b);
  238. }
  239. }
  240. }
  241.  
  242. floyd(n + m + m);
  243.  
  244. low = ;
  245. high = oo;
  246. while (dbcmp(low, high) < ) {
  247. e = ;
  248. memset(first, -, sizeof(first));
  249. mid = (low + high) * 0.5;
  250. for (i = ; i < n; i++) {
  251. for (j = i + ; j < n; j++) {
  252. if (dbcmp(dis[order[i]][order[j]], mid) <= ) {
  253. addEdge(order[i], order[j]);
  254. }
  255. }
  256. }
  257. if (n - match(n) > p) {
  258. low = mid;
  259. } else {
  260. high = mid;
  261. }
  262. }
  263.  
  264. printf("%.2lf\n", mid);
  265.  
  266. }
  267. return ;
  268. }

HDU 4607 Park Visit

最长链上的边走一次,其他边都必须走两次。

dp[i][0]表示以i为根的子树的最大深度,dp[i][1]表示以i为根的子树的次大深度。

答案就是max(dp[i][0]+dp[i][1])。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define MAXN 200010
  5. using namespace std;
  6. int first[MAXN], next[MAXN], v[MAXN], e;
  7. int dp[MAXN][];
  8. bool vis[MAXN];
  9. inline void addEdge(int x, int y) {
  10. v[e] = y;
  11. next[e] = first[x];
  12. first[x] = e++;
  13. }
  14. void dfs(int x) {
  15. vis[x] = true;
  16. dp[x][] = dp[x][] = ;
  17. for (int i = first[x]; i != -; i = next[i]) {
  18. int y = v[i];
  19. if (!vis[y]) {
  20. dfs(y);
  21. if (dp[y][] + >= dp[x][]) {
  22. dp[x][] = dp[x][];
  23. dp[x][] = dp[y][] + ;
  24. } else if (dp[y][] + >= dp[x][]) {
  25. dp[x][] = dp[y][] + ;
  26. }
  27. }
  28. }
  29. }
  30. int main() {
  31. int T;
  32. int n, m;
  33. int i;
  34. int x, y;
  35. scanf("%d", &T);
  36. while (T--) {
  37. scanf("%d%d", &n, &m);
  38. e = ;
  39. memset(first, -, sizeof(first));
  40. for (i = ; i < n; i++) {
  41. scanf("%d%d", &x, &y);
  42. addEdge(x, y);
  43. addEdge(y, x);
  44. }
  45. memset(vis, false, sizeof(vis));
  46. dfs();
  47. x = ;
  48. for (i = ; i <= n; i++) {
  49. x = max(x, dp[i][] + dp[i][]);
  50. }
  51. while (m--) {
  52. scanf("%d", &y);
  53. if (y <= x + ) {
  54. printf("%d\n", y - );
  55. } else {
  56. printf("%d\n", x + * (y - x - ));
  57. }
  58. }
  59. }
  60. return ;
  61. }

HDU 4608I-number

因为y不会比x大多少,所以直接高精度加法暴力。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define MAXN 200010
  5. using namespace std;
  6. int digit[MAXN];
  7. char str[MAXN];
  8. int main() {
  9. int T;
  10. int i;
  11. int len;
  12. int sum;
  13. scanf("%d", &T);
  14. while (T--) {
  15. scanf(" %s", str);
  16. len = strlen(str);
  17. memset(digit, , sizeof(digit));
  18. for (i = ; str[i]; i++) {
  19. digit[i] = str[i] - '';
  20. }
  21. reverse(digit, digit + len);
  22. while () {
  23. digit[]++;
  24. sum = ;
  25. for (i = ; i < len; i++) {
  26. if (digit[i] > ) {
  27. digit[i] -= ;
  28. digit[i + ]++;
  29. if (i == len - ) {
  30. len++;
  31. }
  32. }
  33. sum += digit[i];
  34. }
  35. if (sum % == ) {
  36. break;
  37. }
  38. }
  39. for (i = len - ; i >= ; i--) {
  40. printf("%d", digit[i]);
  41. }
  42. putchar('\n');
  43. }
  44. return ;
  45. }

HDU 4609 3-idiots

对于多项式乘法,普通做法需要O(n2)的时间复杂度。

而FFT仅需要O(nlogn)的时间复杂度。

把三角形边长作为多项式的指数,边长的出现次数作为多项式的系数。

把两个多项式相乘,即可得到任意两边长之和(i)出现的次数(num[i])。

由于一条边只能使用一次,所以num[arr[i]+arr[i]]--。

由于“先a后b”与“先b后a”属于同一种方案,所以num[i]>>=1。

不妨假设a<=b<=c,要构成三角形只要满足a+b>c。

由于a+b>c不容易统计,但是a+b<=c的方案数很容易统计,枚举c就可以做到。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cmath>
  4. #include<algorithm>
  5. #define MAXN 400010
  6. #define EPS 1e-8
  7. typedef long long LL;
  8. using namespace std;
  9. double PI = acos(-1.0);
  10. int arr[MAXN];
  11. LL num[MAXN], sum[MAXN];
  12. struct complex {
  13. double r, i;
  14. complex(double _r = , double _i = ) {
  15. r = _r;
  16. i = _i;
  17. }
  18. complex operator+(const complex &b) {
  19. return complex(r + b.r, i + b.i);
  20. }
  21. complex operator-(const complex &b) {
  22. return complex(r - b.r, i - b.i);
  23. }
  24. complex operator*(const complex &b) {
  25. return complex(r * b.r - i * b.i, r * b.i + i * b.r);
  26. }
  27. };
  28. complex x[MAXN];
  29. void change(complex y[], int len) {
  30. for (int i = , j = len >> ; i < len - ; i++) {
  31. if (i < j) {
  32. swap(y[i], y[j]);
  33. }
  34. int k = len >> ;
  35. for (; j >= k; k >>= ) {
  36. j -= k;
  37. }
  38. if (j < k) {
  39. j += k;
  40. }
  41. }
  42. }
  43. void FFT(complex y[], int len, int on) {
  44. change(y, len);
  45. for (int h = ; h <= len; h <<= ) {
  46. complex wn(cos(-on * * PI / h), sin(-on * * PI / h));
  47. for (int j = ; j < len; j += h) {
  48. complex w(, );
  49. for (int k = j; k < j + (h >> ); k++) {
  50. complex u = y[k];
  51. complex t = w * y[k + (h >> )];
  52. y[k] = u + t;
  53. y[k + (h >> )] = u - t;
  54. w = w * wn;
  55. }
  56. }
  57. }
  58. if (on == -) {
  59. for (int i = ; i < len; i++) {
  60. y[i].r /= len;
  61. }
  62. }
  63. }
  64. int main() {
  65. int T;
  66. int n;
  67. int len, len1;
  68. double ans;
  69. scanf("%d", &T);
  70. while (T--) {
  71. memset(num, , sizeof(num));
  72. scanf("%d", &n);
  73. for (int i = ; i < n; i++) {
  74. scanf("%d", &arr[i]);
  75. num[arr[i]]++;
  76. }
  77. sort(arr, arr + n);
  78. len1 = arr[n - ] + ;
  79. for (len = ; len <= (len1 << ); len <<= )
  80. ;
  81. for (int i = ; i < len1; i++) {
  82. x[i] = complex(num[i], );
  83. }
  84. for (int i = len1; i < len; i++) {
  85. x[i] = complex(, );
  86. }
  87. FFT(x, len, );
  88. for (int i = ; i < len; i++) {
  89. x[i] = x[i] * x[i];
  90. }
  91. FFT(x, len, -);
  92. for (int i = ; i < len; i++) {
  93. num[i] = (LL) (x[i].r + 0.5 + EPS);
  94. }
  95. for (int i = ; i < n; i++) {
  96. num[arr[i] + arr[i]]--;
  97. }
  98. for (int i = ; i < len; i++) {
  99. num[i] >>= ;
  100. }
  101. sum[] = ;
  102. for (int i = ; i < len; i++) {
  103. sum[i] = sum[i - ] + num[i];
  104. }
  105. ans = ;
  106. for (int i = ; i < n; i++) {
  107. ans += sum[arr[i]];
  108. }
  109. printf("%.7lf\n", - ans * / (n * (n - 1.0) * (n - 2.0)));
  110. }
  111. return ;
  112. }

4610 Cards

通过筛素数可以快速判定素数。

条件1,条件2可以快速解决;

条件3,一个数约数之和可能大于该数的好几倍;

条件4,一个数约束的乘积可能爆longlong,要通过分解素因子,判是否是平方数。

由于N的总数不超过20000,N个数的范围都在106内,所以可以O(sqrt(n))的复杂度处理出约数。

由于条件只有4个,所以K个数中,只有24=16个不同种类的数。因此可以枚举每种数是否出现216,贪心的选择。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<vector>
  4. #include<algorithm>
  5. #include<map>
  6. #define oo 987654321
  7. #define MAXP 5000010
  8. #define MAXN 1000010
  9. #define MAXM 4
  10. typedef long long LL;
  11. using namespace std;
  12. bool p[MAXP];
  13. int num[ << MAXM];
  14. int satisfy[MAXN];
  15. int add[MAXM];
  16. vector<int> prime;
  17. void init() {
  18. int i, j;
  19. memset(p, true, sizeof(p));
  20. p[] = p[] = false;
  21. for (i = ; i * i < MAXP; i++) {
  22. if (p[i]) {
  23. for (j = i * i; j < MAXP; j += i) {
  24. p[j] = false;
  25. }
  26. }
  27. }
  28. for (i = ; i < MAXP; i++) {
  29. if (p[i]) {
  30. prime.push_back(i);
  31. }
  32. }
  33. }
  34. bool isSquare(int val, int cnt, int flag) {
  35. map<int, int> mymap;
  36. int i;
  37. for (i = ; prime[i] * prime[i] <= val; i++) {
  38. while (val % prime[i] == ) {
  39. mymap[prime[i]]++;
  40. val /= prime[i];
  41. }
  42. }
  43. if (val > ) {
  44. mymap[val]++;
  45. }
  46. map<int, int>::iterator it;
  47. for (it = mymap.begin(); it != mymap.end(); it++) {
  48. (*it).second *= cnt;
  49. }
  50. for (i = ; prime[i] * prime[i] <= flag; i++) {
  51. while (flag % prime[i] == ) {
  52. mymap[prime[i]]++;
  53. flag /= prime[i];
  54. }
  55. }
  56. if (flag > ) {
  57. mymap[flag]++;
  58. }
  59. for (it = mymap.begin(); it != mymap.end(); it++) {
  60. if ((*it).second & ) {
  61. return false;
  62. }
  63. }
  64. return true;
  65. }
  66. void getSatisfy(int val) {
  67. if (satisfy[val] < ) {
  68. int res = ;
  69. int i;
  70. int amount = ;
  71. int sum = ;
  72. int product = ;
  73. int flag = ;
  74. for (i = ; i * i < val; i++) {
  75. if (val % i == ) {
  76. amount += ;
  77. sum += i + val / i;
  78. product++;
  79. }
  80. }
  81. if (i * i == val) {
  82. amount++;
  83. sum += i;
  84. flag = i;
  85. }
  86. if (p[val]) {
  87. res |= << ;
  88. }
  89. if (p[amount]) {
  90. res |= << ;
  91. }
  92. if (p[sum]) {
  93. res |= << ;
  94. }
  95. if (isSquare(val, product, flag)) {
  96. res |= << ;
  97. }
  98. satisfy[val] = res;
  99. }
  100. }
  101. int numOfOne(int val) {
  102. int res;
  103. for (res = ; val; val >>= ) {
  104. res += val & ;
  105. }
  106. return res;
  107. }
  108. bool cmp(int x, int y) {
  109. return numOfOne(x) > numOfOne(y);
  110. }
  111. int main() {
  112. int T;
  113. int n, k;
  114. int i, j;
  115. int tmp, cnt;
  116. int ans, res;
  117. int sum;
  118. bool flag;
  119. vector<int> g;
  120. init();
  121. memset(satisfy, -, sizeof(satisfy));
  122. scanf("%d", &T);
  123. while (T--) {
  124. memset(num, , sizeof(num));
  125. scanf("%d%d", &n, &k);
  126. for (i = ; i < n; i++) {
  127. scanf("%d%d", &tmp, &cnt);
  128. getSatisfy(tmp);
  129. num[satisfy[tmp]] += cnt;
  130.  
  131. printf("%d", numOfOne(satisfy[tmp]));
  132. if (i < n - ) {
  133. putchar(' ');
  134. } else {
  135. putchar('\n');
  136. }
  137. }
  138. for (i = ; i < MAXM; i++) {
  139. scanf("%d", &add[i]);
  140. }
  141. ans = -oo;
  142. for (i = ; i < ( << ( << MAXM)); i++) {
  143. g.clear();
  144. for (tmp = i, j = ; tmp; tmp >>= , j++) {
  145. if (tmp & ) {
  146. g.push_back(j);
  147. }
  148. }
  149. if ((int) g.size() > k) {
  150. continue;
  151. }
  152. flag = true;
  153. sum = ;
  154. tmp = ;
  155. for (j = ; flag && j < (int) g.size(); j++) {
  156. if (num[g[j]] <= ) {
  157. flag = false;
  158. }
  159. sum += num[g[j]];
  160. tmp |= g[j];
  161. }
  162. if (flag && sum >= k) {
  163. sort(g.begin(), g.end(), cmp);
  164. res = ;
  165. for (j = ; j < MAXM; j++, tmp >>= ) {
  166. if (!(tmp & )) {
  167. res += add[j];
  168. }
  169. }
  170. for (j = ; j < (int) g.size(); j++) {
  171. res += numOfOne(g[j]);
  172. }
  173. tmp = k - g.size();
  174. for (j = ; tmp && j < (int) g.size(); j++) {
  175. cnt = min(tmp, num[g[j]] - );
  176. res += cnt * numOfOne(g[j]);
  177. tmp -= cnt;
  178. }
  179. ans = max(ans, res);
  180. }
  181. }
  182. printf("%d\n", ans);
  183. }
  184. return ;
  185. }

【 2013 Multi-University Training Contest 1 】的更多相关文章

  1. 【 2013 Multi-University Training Contest 8 】

    HDU 4678 Mine 对于每个空白区域,求SG值. 最后异或起来等于0,先手必败. #pragma comment(linker,"/STACK:102400000,102400000 ...

  2. 【 2013 Multi-University Training Contest 7 】

    HDU 4666 Hyperspace 曼哈顿距离:|x1-x2|+|y1-y2|. 最远曼哈顿距离,枚举x1与x2的关系以及y1与y2的关系,取最大值就是答案. #include<cstdio ...

  3. 【 2013 Multi-University Training Contest 6 】

    HDU 4655 Cut Pieces 假设n个数构成的总数都分成了n段,总数是n*a1*a2*...*an.但是答案显然不会那么多. 对于相邻的两个ai,ai+1,如果选择相同的颜色,那么就减少了a ...

  4. 【 2013 Multi-University Training Contest 5 】

    HDU 4647 Another Graph Game 如果没有边的作用,显然轮流拿当前的最大值即可. 加上边的作用,将边权平均分给两个点,如果一个人选走一条边的两个点,就获得了边的权值:如果分别被两 ...

  5. 【 2013 Multi-University Training Contest 4 】

    HDU 4632 Palindrome subsequence dp[x][y]表示区间[x,y]构成回文串的方案数. 若str[x]==str[y],dp[x][y]=dp[x+1][y]+dp[x ...

  6. 【 2013 Multi-University Training Contest 3 】

    HDU 4622 Reincarnation 枚举字符串的起点,构造后缀自动机,每次插入一个字符,就能统计得到当前不同字串的个数,预处理出所有的询问. #include<cstdio> # ...

  7. 【 2013 Multi-University Training Contest 2 】

    HDU 4611 Balls Rearrangement 令lcm=LCM(a,b),gcd=GCD(a,b).cal(n,a,b)表示sum(abs(i%a-i%b)),0<=i<n. ...

  8. 【HDU 2014 Multi-University Training Contest 1 1002】/【HDU 4862】Jump

    多校训练就这么华丽丽的到了 ,于是乎各种华丽丽的被虐也開始了. 这是多校的1002; 最小费用最大流. 题目大意: 有n*m个方格,每一个方格都一个的十进制一位的数.你能够操作K次. 对于每一次操作, ...

  9. 【2018 Multi-University Training Contest 5】

    01: 02:https://www.cnblogs.com/myx12345/p/9436953.html 03: 04: 05:https://www.cnblogs.com/myx12345/p ...

随机推荐

  1. C#字节数组转换成字符串

    C#字节数组转换成字符串 如果还想从 System.String 类中找到方法进行字符串和字节数组之间的转换,恐怕你会失望了.为了进行这样的转换,我们不得不借助另一个类:System.Text.Enc ...

  2. Codeforces Round #388 (Div. 2) A,B,C,D

    A. Bachgold Problem time limit per test 1 second memory limit per test 256 megabytes input standard ...

  3. Cocos2d-x 核心概念 - 坐标系(UI.OpenGL.世界坐标系.模型坐标系)

    UI坐标系与OpenGL坐标系 UI坐标就是Android和IOS等应用开发时候使用的二维坐标系,原点在左上角 OpenGL坐标是三维坐标,由于Cocos2d-x Lua 底层采用OpenGL渲染,因 ...

  4. cocostudio 1.6

    http://cocostudio.download.appget.cn/CocosStudio/v1.6.0.0/CocosStudio_v1.6.0.0.exe

  5. 基础笔记12(socket,url网络通信)

    进一步深入socket 1.网络通信条件: .IP地址,可用主机名. .传输数据时将不用的应用程序通过数字标识区分开来,这种标识称为逻辑端口,也称端口.(0-65535端口,一般系统预留0-1024) ...

  6. js之oop <六>数组的crud(增删改)

    增 Create: push(); 向数组尾添加元素 var arr = [2,6,8,7,4]; arr.push(100); console.log(arr); //输出 [2,6,8,7,4,1 ...

  7. 使用 StringBuilder

    嘿嘿,请不要说我是偷取,我只是借鉴一下.. String 对象是不可改变的.每次使用 System.String 类中的方法之一时,都要在内存中创建一个新的字符串 对象,这就需要为该新对象分配新的空间 ...

  8. eslintrc配置翻译

    { "env": { "browser": true, "node": true, "commonjs": true } ...

  9. Software Engineering: 3. Project planning

    recourse: "Software Engineering", Ian Sommerville Keywords for this chapter: planning sche ...

  10. secureCRT远程登录工具的颜色配置(转载)

    另外,字体和编码设置(如果需要显示中文):Options->Session Options->Appearance->font(字体:幼圆,字形:常规,大小:小三号,字符集:中文GB ...