K小割

题目链接:WC2015 K小割

Description

题目很清楚了,已经不能说的更简洁了……

Solution

这道题出题人挺毒的,你需要针对不同的部分分施用不同的做法 。

  • 第\(1\)部分:暴力枚举每条边是否割掉,并保留所有合法的割,更新答案,最后\(sort\)一下(从小到大),输出即可。

    复杂度\(O(2^m\times n)\),可以规避\(K\)过大的限制。
  • 第\(2\)部分:采用优先队列

    对于除\(s,t\)外的每个点都分别有且仅有一条边与\(s,t\)相连。那么对于每一个点都必须至少割掉其中的一条边。设两条边的权值为\(a,b (a<b)\),那么对于每个点的选择有\(\{a,b,a+b\}\) 三种,我们可以通过对于每个点选择的升级/降级,来达到不同的状态。

    我们将点以\((b-a)\)为第一关键字(从第一级升到第二级的代价),\(a\)为第二关键字排序(从第二级升到第三级的代价)。

    对于每个状态我们有三种选择

    (1)将当前点的状态升级

    (2)当前点保持不变,将该点的后一个点升级,并将当前点改为他后面的点。

    (3)将当前点降级,将该点的后一个点升级,并将当前点改为他后面的点(需要注意的是在降级的时候只能是从\(b->a\),不能是从\(a+b->b\),否则会出现重复的状态,因为\(a+b->b\)的改变其实可以转化成选择(2))

    总之在更新状态的时候需要时刻注意,不要更新到之前已经得到的状态,如果开始后一个点的升级,那么当前点就不能再改变了。
  • 第\(3\)部分:采用最小割

    我们可以先跑最大流,求出最小割

    然后,我们可以按如下方式求出次小割

    \((1)\) 强制割集中的某条边不选,然后求此时的最小割;

    \((2)\) 选择不再割集中的某条边,然后割掉。

    对于第(2)种产生方式,必然是选择不在割集中的边权最小的边来更新答案。那么我们如何确定割集呢?从s开始走剩余流量不为0的边,将所有能遍历到的点打访问标记,如果一条边的两个端点x[i]有标记,y[i]没有标记,那么该边在最小割的割集中。

    第一种情况,对于每一条边来说,如果这条边不割,那么\(s->x[i],y[i]->t\)都其中一个必须不连通,我们可以在做完最小割的残量网络上对于\(s->x[i],y[i]->t\)分别求最小割,然后从中选取较小的更新答案。

    处理完\((1)(2)\)两种产生方式后,得到的答案就是针对当前割集的次小割。

    结合这\(3\)部分,你就可以获得\(AC\)。

混淆与破解

题目链接:WC2015 混淆与破解

Description

Solution

Code

这道题还不会,暂时咕着。

未来程序

题目链接:

Description

这是一道提交答案题

题目给定你\(10\)组\(program*.cpp\)和\(program*.in\),这些都是暴力程序,无法在规定时间内跑出。

你需要优化这\(10\)个程序,并提交对应的\(10\)组\(program*.out\)。

Solution

  • program1
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. void _() {
  4. unsigned long long a, b, c, d, i;
  5. scanf("%llu %llu %llu", &a, &b, &c);
  6. i = 0;
  7. d = 0;
  8. while (i < b) {
  9. d = d + a;
  10. d = d % c;
  11. i = i + 1;
  12. }
  13. printf("%llu\n", d);
  14. }
  15. int main() {
  16. _();
  17. _();
  18. _();
  19. _();
  20. _();
  21. _();
  22. _();
  23. _();
  24. _();
  25. _();
  26. }

这个很显然是求\(a\times b \mod c\),我们用快速乘优化即可。

\(program1.cpp\)

  1. // Author: wlzhouzhuan
  2. #pragma GCC optimize(2)
  3. #pragma GCC optimize(3)
  4. #include <bits/stdc++.h>
  5. using namespace std;
  6. #define ll long long
  7. #define ull unsigned long long
  8. #define rint register int
  9. #define rep(i, l, r) for (rint i = l; i <= r; i++)
  10. #define per(i, l, r) for (rint i = l; i >= r; i--)
  11. #define mset(s, _) memset(s, _, sizeof(s))
  12. #define pb push_back
  13. #define pii pair <int, int>
  14. #define mp(a, b) make_pair(a, b)
  15. inline int read() {
  16. int x = 0, neg = 1; char op = getchar();
  17. while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
  18. while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
  19. return neg * x;
  20. }
  21. inline void print(int x) {
  22. if (x < 0) { putchar('-'); x = -x; }
  23. if (x >= 10) print(x / 10);
  24. putchar(x % 10 + '0');
  25. }
  26. unsigned long long a, b, c;
  27. ull fmul(ull a, ull b, ull c) {
  28. ull ans = 0;
  29. while (b > 0) {
  30. if (b & 1) ans = (ans + a) % c;
  31. a = (a + a) % c;
  32. b >>= 1;
  33. }
  34. return ans;
  35. }
  36. int main() {
  37. freopen("program1.in", "r", stdin);
  38. freopen("program1.out", "w", stdout);
  39. while (cin >> a >> b >> c) {
  40. cout << fmul(a, b, c) << '\n';
  41. }
  42. return 0;
  43. }
  • program2
  1. #include <stdio.h>
  2. void _______() {
  3. long long i, n, a, b, c, d, p;
  4. a = 1;
  5. b = 0;
  6. c = 0;
  7. scanf("%lld %lld", &n, &p);
  8. i = 1;
  9. while (i <= n) {
  10. i = i + 1;
  11. b = a + b;
  12. a = 2 * b - a + c;
  13. c = 2 * b - a + c;
  14. while (a >= p) {
  15. a -= p;
  16. }
  17. while (a < 0) {
  18. a += p;
  19. }
  20. while (b >= p) {
  21. b -= p;
  22. }
  23. while (b < 0) {
  24. b += p;
  25. }
  26. while (c >= p) {
  27. c -= p;
  28. }
  29. while (c < 0) {
  30. c += p;
  31. }
  32. }
  33. d = a - 2 * b + c;
  34. while (d >= p) {
  35. d -= p;
  36. }
  37. while (d < 0) {
  38. d += p;
  39. }
  40. printf("%lld\n", d);
  41. }
  42. int main() {
  43. _______();
  44. _______();
  45. _______();
  46. _______();
  47. _______();
  48. _______();
  49. _______();
  50. _______();
  51. _______();
  52. _______();
  53. return 0;
  54. }

我们发现这其实就是求以\(0\ 1\)开头的斐波那契数列第\(n\)项的平方。

矩阵快速幂优化即可。

\(program2.cpp\)

  1. // Author: wlzhouzhuan
  2. #pragma GCC optimize(2)
  3. #pragma GCC optimize(3)
  4. #include <bits/stdc++.h>
  5. using namespace std;
  6. #define ll long long
  7. #define ull unsigned long long
  8. #define rint register int
  9. #define rep(i, l, r) for (rint i = l; i <= r; i++)
  10. #define per(i, l, r) for (rint i = l; i >= r; i--)
  11. #define mset(s, _) memset(s, _, sizeof(s))
  12. #define pb push_back
  13. #define pii pair <int, int>
  14. #define mp(a, b) make_pair(a, b)
  15. inline int read() {
  16. int x = 0, neg = 1; char op = getchar();
  17. while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
  18. while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
  19. return neg * x;
  20. }
  21. inline void print(int x) {
  22. if (x < 0) { putchar('-'); x = -x; }
  23. if (x >= 10) print(x / 10);
  24. putchar(x % 10 + '0');
  25. }
  26. long long n, mod;
  27. struct Matrix {
  28. ll v[2][2];
  29. int n, m;
  30. Matrix (int _n = 0, int _m = 0) {
  31. n = _n;
  32. m = _m;
  33. }
  34. void clear() {
  35. memset(v, 0, sizeof(v));
  36. }
  37. } ans(2, 1), res(2, 2);
  38. Matrix operator * (Matrix a, Matrix b) {
  39. Matrix ans(a.n, b.m);
  40. ans.clear();
  41. for (rint i = 0; i < a.n; i++) {
  42. for (rint j = 0; j < b.m; j++) {
  43. for (rint k = 0; k < a.m; k++) {
  44. (ans.v[i][j] += a.v[i][k] * b.v[k][j]) %= mod;
  45. }
  46. }
  47. }
  48. return ans;
  49. }
  50. ll fib(ll n) {
  51. if (n == 1) return 0;
  52. if (n == 2) return 1;
  53. ans.clear(), res.clear();
  54. ans.v[0][0] = 1, ans.v[1][0] = 0;
  55. res.v[0][0] = res.v[0][1] = res.v[1][0] = res.v[0][0] = 1;
  56. n -= 2;
  57. while (n > 0) {
  58. if (n & 1) ans = res * ans;
  59. res = res * res;
  60. n >>= 1;
  61. }
  62. return ans.v[0][0];
  63. }
  64. int main() {
  65. freopen("program2.in", "r", stdin);
  66. freopen("program2.out", "w", stdout);
  67. while (cin >> n >> mod) {
  68. ll x = fib(n);
  69. cout << x * x % mod << '\n';
  70. }
  71. return 0;
  72. }
  • program3
  1. #include <stdio.h>
  2. unsigned long long s0, s1, s2, s3, s4, i, n;
  3. int main() {
  4. scanf("%llu", &n);
  5. i = 0;
  6. while (i <= n) {
  7. s0 = s0 + 1;
  8. s1 = s1 + i;
  9. s2 = s2 + i * i;
  10. s3 = s3 + i * i * i;
  11. s4 = s4 + i * i * i * i;
  12. i = i + 1;
  13. }
  14. printf("%llu\n", s0);
  15. printf("%llu\n", s0);
  16. printf("%llu\n", s1);
  17. printf("%llu\n", s1);
  18. printf("%llu\n", s2);
  19. printf("%llu\n", s2);
  20. printf("%llu\n", s3);
  21. printf("%llu\n", s3);
  22. printf("%llu\n", s4);
  23. printf("%llu\n", s4);
  24. return 0;
  25. }

这是让我们求

\[s0=\sum_{i=1}^{n}1
\]
\[s1=\sum_{i=1}^{n}i
\]
\[s2=\sum_{i=1}^{n}i^2
\]
\[s3=\sum_{i=1}^{n}i^3
\]
\[s4=\sum_{i=1}^{n}i^4
\]

直接套数学公式即可,四次方和公式可别忘了呐~

\(program3.cpp\)

  1. // Author: wlzhouzhuan
  2. #pragma GCC optimize(2)
  3. #pragma GCC optimize(3)
  4. #include <bits/stdc++.h>
  5. using namespace std;
  6. #define ll long long
  7. #define ull unsigned long long
  8. #define rint register int
  9. #define rep(i, l, r) for (rint i = l; i <= r; i++)
  10. #define per(i, l, r) for (rint i = l; i >= r; i--)
  11. #define mset(s, _) memset(s, _, sizeof(s))
  12. #define pb push_back
  13. #define pii pair <int, int>
  14. #define mp(a, b) make_pair(a, b)
  15. inline int read() {
  16. int x = 0, neg = 1; char op = getchar();
  17. while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
  18. while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
  19. return neg * x;
  20. }
  21. inline void print(int x) {
  22. if (x < 0) { putchar('-'); x = -x; }
  23. if (x >= 10) print(x / 10);
  24. putchar(x % 10 + '0');
  25. }
  26. ull n;
  27. int main() {
  28. freopen("program3.in", "r", stdin);
  29. freopen("program3.out", "w", stdout);
  30. while (cin >> n) {
  31. ull ans = n + 1;
  32. cout << ans << '\n';
  33. cout << ans << '\n';
  34. ans = n * (n + 1) / 2ull;
  35. cout << ans << '\n';
  36. cout << ans << '\n';
  37. ans = n * (n + 1) * (2 * n + 1) / 6ull;
  38. cout << ans << '\n';
  39. cout << ans << '\n';
  40. ans = n * (n + 1) / 2ull;
  41. ans = ans * ans;
  42. cout << ans << '\n';
  43. cout << ans << '\n';
  44. ull a[5] = {n, n + 1, 2 * n + 1, 3 * n * n + 3 * n - 1};
  45. ull ne[5] = {2, 3, 5};
  46. for (rint i = 0; i < 3; i++) {
  47. for (rint j = 0; j < 4; j++) {
  48. if (a[j] % ne[i] == 0) {
  49. a[j] /= ne[i];
  50. break;
  51. }
  52. }
  53. }
  54. ans = a[0] * a[1] * a[2] * a[3];
  55. //ans = n * (n + 1) * (2ull * n + 1ull) / 30ull * (3ull * n * n + 3ull * n - 1ull);
  56. cout << ans << '\n';
  57. cout << ans << '\n';
  58. }
  59. }
  • program4
  1. #include <iostream>
  2. const int N = 5000, inf = 0x3F3F3F3F;
  3. int n, m, type;
  4. bool data[N + 11][N + 11];
  5. int seed;
  6. int next_rand(){
  7. static const int P = 1000000007, Q = 83978833, R = 8523467;
  8. return seed = ((long long)Q * seed % P * seed + R) % P;
  9. }
  10. void generate_input(){
  11. std::cin >> n >> m >> type;
  12. for(int i = 0; i < n; i++)
  13. for(int j = 0; j < m; j++)
  14. data[i][j] = bool((next_rand() % 8) > 0);
  15. }
  16. long long count1(){
  17. long long ans = 0LL;
  18. for(int i = 0; i < n; i++)
  19. for(int j = 0; j < m; j++)
  20. if(data[i][j])
  21. for(int k = 0; k < n; k++)
  22. for(int l = 0; l < m; l++)
  23. if(data[k][l] && (k != i || l != j))
  24. ans++;
  25. return ans;
  26. }
  27. int abs_int(int x){
  28. return x < 0 ? -x : x;
  29. }
  30. long long count2(){
  31. long long ans = 0LL;
  32. for(int i = 0; i < n; i++)
  33. for(int j = 0; j < m; j++)
  34. if(data[i][j]){
  35. int level = inf;
  36. for(int k = 0; k < n; k++)
  37. for(int l = 0; l < m; l++)
  38. if(!data[k][l]){
  39. int dist = abs_int(k - i) + abs_int(l - j);
  40. if(level > dist)
  41. level = dist;
  42. }
  43. ans += level;
  44. }
  45. return ans;
  46. }
  47. int main(){
  48. std::cin >> seed;
  49. for(int i = 0; i < 10; i++){
  50. generate_input();
  51. std::cout << (type == 1 ? count2() : count1()) << std::endl;
  52. }
  53. return 0;
  54. }

这道题如果\(type=0\),那么就是求有多少对二元组\(((x_i,y_i),(x_j,y_j))\ (i≠j)\),满足\(data_{x_i,y_i}=1\)且\(data_{x_j,y_j}=1\)。

如果\(type=1\),那么就是求每一个\(x_i,y_i\)满足\(data_{x_i,y_i}=1\),离它曼哈顿距离最近的\(data_{x_j,y_j}=0\)距离之和。

显然直接\(dp\)即可。

\(program4.cpp\)

  1. // Author: wlzhouzhuan
  2. #pragma GCC optimize(2)
  3. #pragma GCC optimize(3)
  4. #include <bits/stdc++.h>
  5. using namespace std;
  6. #define ll long long
  7. #define ull unsigned long long
  8. #define rint register int
  9. #define rep(i, l, r) for (rint i = l; i <= r; i++)
  10. #define per(i, l, r) for (rint i = l; i >= r; i--)
  11. #define mset(s, _) memset(s, _, sizeof(s))
  12. #define pb push_back
  13. #define pii pair <int, int>
  14. #define mp(a, b) make_pair(a, b)
  15. inline int read() {
  16. int x = 0, neg = 1; char op = getchar();
  17. while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
  18. while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
  19. return neg * x;
  20. }
  21. inline void print(int x) {
  22. if (x < 0) { putchar('-'); x = -x; }
  23. if (x >= 10) print(x / 10);
  24. putchar(x % 10 + '0');
  25. }
  26. const int N = 5005;
  27. int data[N][N];
  28. int seed, n, m, type;
  29. int next_rand() {
  30. static const int P = 1000000007, Q = 83978833, R = 8523467;
  31. return seed = ((long long)Q * seed % P * seed + R) % P;
  32. }
  33. void generate_input() {
  34. cin >> n >> m >> type;
  35. for (rint i = 1; i <= n; i++) {
  36. for (rint j = 1; j <= m; j++) {
  37. data[i][j] = bool((next_rand() % 8) > 0);
  38. }
  39. }
  40. }
  41. long long count1() {
  42. long long ans = 0ll;
  43. for (rint i = 1; i <= n; i++) {
  44. for (rint j = 1; j <= m; j++) {
  45. if (data[i][j] == 1) {
  46. ans++;
  47. }
  48. }
  49. }
  50. return ans * (ans - 1);
  51. }
  52. int dp1[N][N];
  53. int dp2[N][N];
  54. int dp3[N][N];
  55. int dp4[N][N];
  56. long long count2() {
  57. mset(dp1, 0x3f), mset(dp2, 0x3f), mset(dp3, 0x3f), mset(dp4, 0x3f);
  58. for (rint i = 1; i <= n; i++) {
  59. for (rint j = 1; j <= m; j++) {
  60. if (!data[i][j]) dp1[i][j] = 0;
  61. else dp1[i][j] = min(dp1[i - 1][j], dp1[i][j - 1]) + 1;
  62. }
  63. }
  64. for (rint i = 1; i <= n; i++) {
  65. for (rint j = m; j >= 1; j--) {
  66. if (!data[i][j]) dp2[i][j] = 0;
  67. else dp2[i][j] = min(dp2[i - 1][j], dp2[i][j + 1]) + 1;
  68. }
  69. }
  70. for (rint i = n; i >= 1; i--) {
  71. for (rint j = 1; j <= m; j++) {
  72. if (!data[i][j]) dp3[i][j] = 0;
  73. else dp3[i][j] = min(dp3[i + 1][j], dp3[i][j - 1]) + 1;
  74. }
  75. }
  76. for (rint i = n; i >= 1; i--) {
  77. for (rint j = m; j >= 1; j--) {
  78. if (!data[i][j]) dp4[i][j] = 0;
  79. else dp4[i][j] = min(dp4[i + 1][j], dp4[i][j + 1]) + 1;
  80. }
  81. }
  82. long long ans = 0ll;
  83. for (rint i = 1; i <= n; i++) {
  84. for (rint j = 1; j <= m; j++) {
  85. if (data[i][j]) {
  86. ans += min(min(dp1[i][j], dp2[i][j]), min(dp3[i][j], dp4[i][j]));
  87. }
  88. }
  89. }
  90. return ans;
  91. }
  92. int main() {
  93. freopen("program4.in", "r", stdin);
  94. freopen("program4.out", "w", stdout);
  95. cin >> seed;
  96. for (rint i = 0; i < 10; i++) {
  97. generate_input();
  98. cout << (type == 1 ? count2() : count1()) << endl;
  99. }
  100. return 0;
  101. }
  • program5
  1. #include <iostream>
  2. const int N = 5011;
  3. int n, m;
  4. bool data[N][N];
  5. int seed;
  6. int next_rand(){
  7. static const int P = 1000000007, Q = 83978833, R = 8523467;
  8. return seed = ((long long)Q * seed % P * seed + R) % P;
  9. }
  10. void generate_input(){
  11. std::cin >> n >> m;
  12. for(int i = 0; i < n; i++)
  13. for(int j = 0; j < m; j++)
  14. data[i][j] = bool((next_rand() % 8) > 0);
  15. }
  16. bool check(int x1, int y1, int x2, int y2){
  17. bool flag = true;
  18. for(int i = x1; i <= x2; i++)
  19. for(int j = y1; j <= y2; j++)
  20. if(!data[i][j])
  21. flag = false;
  22. return flag;
  23. }
  24. long long count3(){
  25. long long ans = 0;
  26. for(int i = 0; i < n; i++)
  27. for(int j = 0; j < m; j++)
  28. for(int k = i; k < n; k++)
  29. for(int l = j; l < m; l++)
  30. if(check(i, j, k, l))
  31. ans++;
  32. return ans;
  33. }
  34. int main(){
  35. std::cin >> seed;
  36. for(int i = 0; i < 10; i++){
  37. generate_input();
  38. std::cout << count3() << std::endl;
  39. }
  40. return 0;
  41. }

题目问你有多少个内部全是\(1\)的矩阵。

我们先表示:

\(h_{i,j}\)表示\((i,j)\)这个点往上连续\(1\)的最长长度。

\(l_{i,j}\)表示从\((i,j)\)开始第一个满足\(h_{i,l_{i,j}}\le h(i,j)\)的点,如果不存在,令\(l_{i,j}=0\)。

\(r_{i,j}\)表示从\((i,j)\)开始第一个满足\(h_{i,r_{i,j}}\le h(i,j)\)的点,如果不存在,令\(r_{i,j}=m+1\)。

那么,对于\((i,j)\)为矩形底的贡献,就是\(val=(j-l_{i,j})*(r_{i,j}-j)*h_{i,j}\)。

考虑一下,这样做如何保证答案不重不漏。

不重:当且仅当在同一行存在两个数\(l_{i,j_1}=l_{i,j_2}\)并且\(r_{i,j_1}=r_{i,j_2}\)的时候,才有可能算重矩形。

但是这种情况是不存在的,因为\(l_{i,j}\)满足了左边第一个小于等于的,右边第一个小于的,显然无法构造出这种情况。

不漏:对于一个矩形,总有一个\(l_{i,j},r_{i,j}\)能框住一个矩形的两边,故这个矩形一定能被计算到。

我们可以通过一个单调栈来计算\(l_{i,j}\)和\(r_{i,j}\),复杂度\(O(n^2)\)。

但是我写代码的时候\(sb\)了,所以用了一个单调队列来维护,但本质上是一样的。

\(program5.cpp\)

  1. // Author: wlzhouzhuan
  2. #pragma GCC optimize(2)
  3. #pragma GCC optimize(3)
  4. #include <bits/stdc++.h>
  5. using namespace std;
  6. #define ll long long
  7. #define ull unsigned long long
  8. #define rint register int
  9. #define rep(i, l, r) for (rint i = l; i <= r; i++)
  10. #define per(i, l, r) for (rint i = l; i >= r; i--)
  11. #define mset(s, _) memset(s, _, sizeof(s))
  12. #define pb push_back
  13. #define pii pair <int, int>
  14. #define mp(a, b) make_pair(a, b)
  15. inline int read() {
  16. int x = 0, neg = 1; char op = getchar();
  17. while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
  18. while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
  19. return neg * x;
  20. }
  21. inline void print(int x) {
  22. if (x < 0) { putchar('-'); x = -x; }
  23. if (x >= 10) print(x / 10);
  24. putchar(x % 10 + '0');
  25. }
  26. const int N = 5005;
  27. int a[N][N], h[N][N], l[N][N], r[N][N];
  28. int seed, n, m;
  29. int next_rand() {
  30. static const int P = 1000000007, Q = 83978833, R = 8523467;
  31. return seed = ((long long)Q * seed % P * seed + R) % P;
  32. }
  33. void generate_input() {
  34. cin >> n >> m;
  35. for (rint i = 1; i <= n; i++) {
  36. for (rint j = 1; j <= m; j++) {
  37. a[i][j] = bool((next_rand() % 8) > 0);
  38. }
  39. }
  40. }
  41. deque <int> deq;
  42. void push_l(int i, int j) {
  43. while (!deq.empty() && h[i][deq.back()] > h[i][j]) r[i][deq.back()] = j, deq.pop_back();
  44. deq.push_back(j);
  45. }
  46. void push_r(int i, int j) {
  47. while (!deq.empty() && h[i][deq.back()] >= h[i][j]) l[i][deq.back()] = j, deq.pop_back();
  48. deq.push_back(j);
  49. }
  50. long long count3() {
  51. for (rint j = 1; j <= m; j++) {
  52. for (rint i = 1; i <= n; i++) {
  53. if (a[i][j]) h[i][j] = h[i - 1][j] + 1;
  54. else h[i][j] = 0;
  55. }
  56. }
  57. long long ans = 0ll;
  58. for (rint i = 1; i <= n; i++) {
  59. while (!deq.empty()) deq.pop_back();
  60. for (rint j = 1; j <= m; j++) {
  61. push_l(i, j);
  62. }
  63. while (!deq.empty()) r[i][deq.back()] = m + 1, deq.pop_back();
  64. for (rint j = m; j >= 1; j--) {
  65. push_r(i, j);
  66. }
  67. while (!deq.empty()) l[i][deq.back()] = 0, deq.pop_back();
  68. for (rint j = 1; j <= m; j++) {
  69. //printf("l[%d][%d] = %d, r[%d][%d] = %d\n", i, j, l[i][j], i, j, r[i][j]);
  70. //printf("h[%d][%d] = %d\n", i, j, h[i][j]);
  71. ans += 1ll * (j - l[i][j]) * (r[i][j] - j) * h[i][j];
  72. }
  73. }
  74. return ans;
  75. }
  76. int main() {
  77. freopen("program5.in", "r", stdin);
  78. freopen("program5.out", "w", stdout);
  79. cin >> seed;
  80. for (rint i = 0; i < 10; i++) {
  81. generate_input();
  82. cout << count3() << endl;
  83. }
  84. return 0;
  85. }
  • program6
  1. #include <stdio.h>
  2. unsigned long long a, b, c, t, k, n;
  3. unsigned long long rd() {
  4. t = (t * t * a + b) % c;
  5. return t;
  6. }
  7. int main() {
  8. int i;
  9. for (i = 0; i <= 9; i++) {
  10. scanf("%llu %llu %llu %llu", &n, &a, &b, &c);
  11. t = 0;
  12. k = 1;
  13. while (k <= n) {
  14. k = k + 1;
  15. rd();
  16. }
  17. printf("%llu\n", t);
  18. }
  19. }

这道题让你计算\(n\)次\(t=(t*t*a+b)\%c\),很显然直接做是不行的。

我们考虑用\(Floyd\)判圈法。

形象的说,就是乌龟赛跑。乌龟每次走\(1\)步,兔子每次跑\(2\)步,如果这个\(t\)的取值存在循环,即图存在环,那么乌龟和兔子就会相遇。

具体见这篇博客,有讲两种判圈算法。

\(program6.cpp\)

  1. // Author: wlzhouzhuan
  2. #pragma GCC optimize(2)
  3. #pragma GCC optimize(3)
  4. #include <bits/stdc++.h>
  5. using namespace std;
  6. #define ll long long
  7. #define ull unsigned long long
  8. #define rint register int
  9. #define rep(i, l, r) for (rint i = l; i <= r; i++)
  10. #define per(i, l, r) for (rint i = l; i >= r; i--)
  11. #define mset(s, _) memset(s, _, sizeof(s))
  12. #define pb push_back
  13. #define pii pair <int, int>
  14. #define mp(a, b) make_pair(a, b)
  15. inline int read() {
  16. int x = 0, neg = 1; char op = getchar();
  17. while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
  18. while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
  19. return neg * x;
  20. }
  21. inline void print(int x) {
  22. if (x < 0) { putchar('-'); x = -x; }
  23. if (x >= 10) print(x / 10);
  24. putchar(x % 10 + '0');
  25. }
  26. ull n, a, b, c;
  27. void nxt(ull &t) {
  28. t = (t * t * a + b) % c;
  29. }
  30. int main() {
  31. freopen("program6.in", "r", stdin);
  32. freopen("program6.out", "w", stdout);
  33. for (rint t = 0; t <= 9; t++) {
  34. scanf("%llu%llu%llu%llu", &n, &a, &b, &c);
  35. int tot = 0;
  36. ull x = 0, y = 0;
  37. do {
  38. tot++;
  39. nxt(x), nxt(y), nxt(y);
  40. } while (x != y);
  41. cerr << "meet\n";
  42. int cycle = 0;
  43. do {
  44. cycle++;
  45. nxt(x);
  46. } while (x != y);
  47. cerr << "cycle = " << cycle << '\n';
  48. int turns = (n - tot) % cycle;
  49. while (turns--) {
  50. nxt(y);
  51. }
  52. printf("%llu\n", y);
  53. }
  54. return 0;
  55. }
  • program7
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <iostream>
  4. using namespace std;
  5. char s[20][20];
  6. bool check() {
  7. for (int i = 0; i <= 15; i++) {
  8. bool v[16];
  9. memset(v, false, sizeof(v));
  10. for (int j = 0; j <= 15; j++) {
  11. v[s[i][j] - 'A'] = true;
  12. }
  13. for (int j = 0; j <= 15; j++) {
  14. if (!v[j]) {
  15. return false;
  16. }
  17. }
  18. }
  19. for (int i = 0; i <= 15; i++) {
  20. bool v[16];
  21. memset(v, false, sizeof(v));
  22. for (int j = 0; j <= 15; j++) {
  23. v[s[j][i] - 'A'] = true;
  24. }
  25. for (int j = 0; j <= 15; j++) {
  26. if (!v[j]) {
  27. return false;
  28. }
  29. }
  30. }
  31. for (int i = 0; i <= 15; i++) {
  32. bool v[16];
  33. memset(v, false, sizeof(v));
  34. for (int j = 0; j <= 15; j++) {
  35. v[s[i / 4 * 4 + j / 4][i % 4 * 4 + j % 4] - 'A'] = true;
  36. }
  37. for (int j = 0; j <= 15; j++) {
  38. if (!v[j]) {
  39. return false;
  40. }
  41. }
  42. }
  43. return true;
  44. }
  45. bool dfs(int x, int y) {
  46. if (x == 16 && y == 0) {
  47. return check();
  48. }
  49. if (s[x][y] == '?') {
  50. for (char i = 'A'; i <= 'P'; i++) {
  51. s[x][y] = i;
  52. if (dfs(x, y)) {
  53. return true;
  54. }
  55. s[x][y] = '?';
  56. }
  57. return false;
  58. } else {
  59. return dfs(x + (y + 1) / 16, (y + 1) % 16);
  60. }
  61. }
  62. void solve(int points) {
  63. for (int i = 0; i <= 15; i++) {
  64. scanf("%s", s[i]);
  65. }
  66. if (dfs(0, 0)) {
  67. for (int k = 0; k <= points - 1; k++) {
  68. for (int i = 0; i <= 15; i++) {
  69. printf("%s", s[i]);
  70. }
  71. putchar('\n');
  72. }
  73. } else {
  74. for (int k = 0; k <= points - 1; k++) {
  75. printf("NO SOLUTION.\n");
  76. }
  77. }
  78. }
  79. int main() {
  80. solve(1);
  81. solve(2);
  82. solve(3);
  83. solve(4);
  84. return 0;
  85. }

这是……“字母”独?

给了你一个\(16\times 16\)的矩阵,你需要填上\(A-P\),使得每行每列以及16个\(4\times 4\)的宫内刚好是\(A-P\)这16个字母。

正着扫当然\(TLE\),于是我们考虑倒着扫~

倒着扫竟然只要\(3-\)秒,太神仙了!

PS: 看来以后爆搜的题目倒着扫优秀点 /cy

\(program7.cpp\)

  1. // Author: wlzhouzhuan
  2. #pragma GCC optimize(2)
  3. #pragma GCC optimize(3)
  4. #include <bits/stdc++.h>
  5. using namespace std;
  6. #define ll long long
  7. #define ull unsigned long long
  8. #define rint register int
  9. #define rep(i, l, r) for (rint i = l; i <= r; i++)
  10. #define per(i, l, r) for (rint i = l; i >= r; i--)
  11. #define mset(s, _) memset(s, _, sizeof(s))
  12. #define pb push_back
  13. #define pii pair <int, int>
  14. #define mp(a, b) make_pair(a, b)
  15. inline int read() {
  16. int x = 0, neg = 1; char op = getchar();
  17. while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
  18. while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
  19. return neg * x;
  20. }
  21. inline void print(int x) {
  22. if (x < 0) { putchar('-'); x = -x; }
  23. if (x >= 10) print(x / 10);
  24. putchar(x % 10 + '0');
  25. }
  26. const int N = 50;
  27. char s[N][N];
  28. int pw[N], row[N], col[N], block[N];
  29. int be(int x, int y) {
  30. return 4 * (x / 4) + (y / 4);
  31. }
  32. int opt = 0;
  33. void dfs(int x, int y) {
  34. if (x == -1) {
  35. opt = 1;
  36. return ;
  37. }
  38. if (opt) return ;
  39. if (!opt && s[x][y] != '?') {
  40. if (y == 0) dfs(x - 1, 15);
  41. else dfs(x, y - 1);
  42. } else {
  43. for (rint i = 0; i <= 15; i++) {
  44. if (opt) return ;
  45. if (!opt && !((row[x] >> i) & 1) && !((col[y] >> i) & 1) && !((block[be(x, y)] >> i) & 1)) {
  46. row[x] ^= pw[i];
  47. col[y] ^= pw[i];
  48. block[be(x, y)] ^= pw[i];
  49. s[x][y] = 'A' + i;
  50. if (y == 0) dfs(x - 1, 15);
  51. else dfs(x, y - 1);
  52. if (opt) return ;
  53. s[x][y] = '?';
  54. row[x] ^= pw[i];
  55. col[y] ^= pw[i];
  56. block[be(x, y)] ^= pw[i];
  57. }
  58. }
  59. }
  60. }
  61. void solve(int points) {
  62. memset(row, 0, sizeof(row));
  63. memset(col, 0, sizeof(col));
  64. memset(block, 0, sizeof(block));
  65. for (rint i = 0; i <= 15; i++) {
  66. scanf("%s", s[i]);
  67. for (rint j = 0; j <= 15; j++) {
  68. if (s[i][j] != '?') {
  69. row[i] ^= pw[s[i][j] - 'A'];
  70. col[j] ^= pw[s[i][j] - 'A'];
  71. block[be(i, j)] ^= pw[s[i][j] - 'A'];
  72. }
  73. }
  74. }
  75. opt = 0, dfs(15, 15);
  76. if (opt == 1) {
  77. for (rint k = 0; k <= points - 1; k++) {
  78. for (rint i = 0; i <= 15; i++) {
  79. printf("%s", s[i]);
  80. }
  81. putchar('\n');
  82. }
  83. } else {
  84. for (rint k = 0; k <= points - 1; k++) {
  85. puts("NO SOLUTION.");
  86. }
  87. }
  88. }
  89. int main() {
  90. freopen("program7.in", "r", stdin);
  91. freopen("program7.out", "w", stdout);
  92. pw[0] = 1;
  93. for (rint i = 1; i <= 15; i++) pw[i] = pw[i - 1] << 1;
  94. solve(1), solve(2), solve(3), solve(4);
  95. return 0;
  96. }
  • program8
  1. #include <stdio.h>
  2. unsigned long long a, b, c, d, e, f, g, n, q, r, s, t, u, v, w, x, y, z;
  3. unsigned long long p = 1234567891;
  4. int main() {
  5. scanf("%llu", &n);
  6. a = 0;
  7. q = 0;
  8. r = 0;
  9. s = 0;
  10. t = 0;
  11. u = 0;
  12. v = 0;
  13. w = 0;
  14. x = 0;
  15. y = 0;
  16. z = 0;
  17. a = 0;
  18. while (a < n) {
  19. a = a + 1;
  20. b = 0;
  21. while (b < n) {
  22. b = b + 1;
  23. c = 0;
  24. while (c < n) {
  25. c = c + 1;
  26. d = 0;
  27. while (d < n) {
  28. d = d + 1;
  29. e = 0;
  30. while (e < n) {
  31. e = e + 1;
  32. f = 0;
  33. while (f < n) {
  34. f = f + 1;
  35. g = 0;
  36. while (g < n) {
  37. g = g + 1;
  38. if (a < b && b < c && c < d && d < e && e < f && f < g) {
  39. q = q + 1;
  40. q = q % p;
  41. }
  42. if (a < b && c < g && c < d && e < f && a < d) {
  43. r = r + 1;
  44. r = r % p;
  45. }
  46. if (a < d && d < f && c < f && c < e && b < d) {
  47. s = s + 1;
  48. s = s % p;
  49. }
  50. if (d < e && b < d && a < f && d < e && b < g) {
  51. t = t + 1;
  52. t = t % p;
  53. }
  54. if (c < f && b < f && b < c && f < g && b < f) {
  55. u = u + 1;
  56. u = u % p;
  57. }
  58. if (b < d && b < c && d < f && c < e && b < e) {
  59. v = v + 1;
  60. v = v % p;
  61. }
  62. if (a < c && a < b && c < e && b < f && e < g) {
  63. w = w + 1;
  64. w = w % p;
  65. }
  66. if (b < d && b < f && a < g && c < g && a < e) {
  67. x = x + 1;
  68. x = x % p;
  69. }
  70. if (b < f && a < c && c < d && a < c && b < e) {
  71. y = y + 1;
  72. y = y % p;
  73. }
  74. if (d < e && e < f && a < d && c < g && b < d) {
  75. z = z + 1;
  76. z = z % p;
  77. }
  78. }
  79. }
  80. }
  81. }
  82. }
  83. }
  84. }
  85. printf("%llu\n", q);
  86. printf("%llu\n", r);
  87. printf("%llu\n", s);
  88. printf("%llu\n", t);
  89. printf("%llu\n", u);
  90. printf("%llu\n", v);
  91. printf("%llu\n", w);
  92. printf("%llu\n", x);
  93. printf("%llu\n", y);
  94. printf("%llu\n", z);
  95. return 0;
  96. }

仔细观察,我们就会发现,其实程序就是求了10组组合问题。组合数随便搞搞就可以得到答案。

\(program8.cpp\)

  1. // Author: wlzhouzhuan
  2. #pragma GCC optimize(2)
  3. #pragma GCC optimize(3)
  4. #include <bits/stdc++.h>
  5. using namespace std;
  6. #define ll long long
  7. #define ull unsigned long long
  8. #define rint register int
  9. #define rep(i, l, r) for (rint i = l; i <= r; i++)
  10. #define per(i, l, r) for (rint i = l; i >= r; i--)
  11. #define mset(s, _) memset(s, _, sizeof(s))
  12. #define pb push_back
  13. #define pii pair <int, int>
  14. #define mp(a, b) make_pair(a, b)
  15. inline int read() {
  16. int x = 0, neg = 1; char op = getchar();
  17. while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
  18. while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
  19. return neg * x;
  20. }
  21. inline void print(int x) {
  22. if (x < 0) { putchar('-'); x = -x; }
  23. if (x >= 10) print(x / 10);
  24. putchar(x % 10 + '0');
  25. }
  26. ull n, p = 1234567891;
  27. ull ksm(ull a, ull b) {
  28. ull res = 1;
  29. while (b > 0) {
  30. if (b & 1) res = res * a % p;
  31. a = a * a % p;
  32. b >>= 1;
  33. }
  34. return res;
  35. }
  36. int main() {
  37. freopen("program8.in", "r", stdin);
  38. freopen("program8.out", "w", stdout);
  39. scanf("%llu", &n);
  40. n %= p;
  41. printf("%I64u\n",n>6?(n*(n-1)%p*(n-2)%p*(n-3)%p*(n-4)%p*(n-5)%p*(n-6)%p*ksm(5040,p-2)%p):0);
  42. printf("%I64u\n",n>1?((n-1)*(n-1)%p*n%p*n%p*(2*n-1)%p*(2*n%p*n%p-2*n%p+1+p)%p*ksm(60,p-2)%p):0);
  43. printf("%I64u\n",n>2?(n*n%p*(n-1)%p*(n-1)%p*(n-2)%p*(2*n-1)%p*(7*n-3)%p*ksm(360,p-2)%p):0);
  44. printf("%I64u\n",n>2?(n*n%p*n%p*(n-1)%p*(n-1)%p*(n-2)%p*(3*n-1)%p*ksm(48,p-2)%p):0);
  45. printf("%I64u\n",n>3?(n*n%p*n%p*n%p*(n-1)%p*(n-2)%p*(n-3)%p*ksm(24,p-2)%p):0);
  46. printf("%I64u\n",n>2?(n*n%p*n%p*(n-1)%p*(n-2)%p*(3*n*n%p-6*n%p+1+p)%p*ksm(60,p-2)%p):0);
  47. printf("%I64u\n",n>3?(n*n%p*(n-1)%p*(n-2)%p*(n-3)%p*(5*n*n%p-9*n%p+1+p)%p*ksm(360,p-2)%p):0);
  48. printf("%I64u\n",n>1?(n*n%p*(n-1)%p*(n-1)%p*(2*n-1)%p*(5*n%p*n%p-5*n%p+2+p)%p*ksm(144,p-2)%p):0);
  49. printf("%I64u\n",n>2?(n*n%p*n%p*(n-1)%p*(n-1)%p*(n-2)%p*(2*n-1)%p*ksm(36,p-2)%p):0);
  50. printf("%I64u\n",n>3?(n*n%p*(n-1)%p*(n-1)%p*(n-2)%p*(n-3)%p*(2*n-3)%p*ksm(240,p-2)%p):0);
  51. return 0;
  52. }

最后两组是恶搞(\(program9\)扯出\(chenlijie\)大神和\(MD5\)解密,\(program10\)扯出《独立宣言》,数每个字母出现的次数,并进行\(hash\))

参考:

https://www.cnblogs.com/ljh2000-jump/p/6268775.html

WC2015 题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. 【Android开发】Android 删除指定文件和文件夹

    /** * 删除单个文件 * @param filePath 被删除文件的文件名 * @return 文件删除成功返回true,否则返回false */ public boolean deleteFi ...

  2. Spring MVC框架搭建及其详解

    现在主流的Web MVC框架除了Struts这个主力 外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了.不过 ...

  3. Vulnhub 之 Earth

    靶机地址:https://www.vulnhub.com/entry/the-planets-earth,755/ Kali IP:192.168.56.104 下载OVA文件后,直接通过Virtua ...

  4. 实现WebMvcConfigurer接口扩展Spring MVC的功能

    前言: 先查看WebMvcConfigurer接口中都定义了哪些内容 public interface WebMvcConfigurer { default void configurePathMat ...

  5. 8.Jenkins进阶之流水线pipeline基础使用实践(1)

    ​目录一览: 0x01 基础实践 (1) Maven 构建之 Pipeline Script (2) Maven 构建之 Pipeline Script from SCM (3) Jenkins pi ...

  6. 新手入门C语言第七章:C判断

    C 判断 判断结构要求程序员指定一个或多个要评估或测试的条件,以及条件为真时要执行的语句(必需的)和条件为假时要执行的语句(可选的). C 语言把任何非零和非空的值假定为 true,把零或 null  ...

  7. C#/VB.NET 将RTF转为HTML

    RTF文档即富文本格式(Rich Text Format)的文档.我们在处理文件时,遇到需要对文档格式进行转换时,可以将RTF转为其他格式,如转为DOCX/DOC.PDF或者HTML,以满足程序设计需 ...

  8. 关于Android安装apk出现解析包异常问题情况总结

    原文地址:关于Android安装apk出现解析包异常问题情况总结 | Stars-One的杂货小窝 说之前,可以推荐下各位使用这个开源库AndroidUtilCode,下面提及到的工具类,都是在此库中 ...

  9. 基于深度学习的车辆检测系统(MATLAB代码,含GUI界面)

    摘要:当前深度学习在目标检测领域的影响日益显著,本文主要基于深度学习的目标检测算法实现车辆检测,为大家介绍如何利用\(\color{#4285f4}{M}\color{#ea4335}{A}\colo ...

  10. 【论文笔记】A Survey on Federated Learning: The Journey From Centralized to Distributed On-Site Learning and Beyond(综述)

    A Survey on Federated Learning: The Journey From Centralized to Distributed On-Site Learning and Bey ...