zoukankan      html  css  js  c++  java
  • 「考前日志」11.17

    总结

    最近真的很不对劲

    打不起精神头来

    而且电脑还巨卡

    一天做不了几道题

    挺压抑的

    上一次这种情况是在三月份了……

    我该怎么办啊

    ⑨⑨⑤⑧

    今日已完成

    • AcWing291 蒙德里安的梦想

      状压DP。
      以行数以及此行的形态为状态。
      (f_{i,j}) 表示前 (i) 行,第 (i) 行形态为 (j) 时的方案总数。
      此处 (j) 是一个用十进制整数记录的 (m) 位二进制数。
      如果 (j) 二进制下当前位置为 (1),说明该位置为某个小长方形的上半部分,下一行的当前位置一定要放下半部分(即为 (0))。
      如果为 (0) 表示其他情况,对下一行的形态无影响,但要保证连续的 (0) 的个数为偶数个。
      对于当前行 (i) 的形态 (j),可以由上一行 (i- 1) 的形态 (k) 转移过来当且仅当:

      • 当前行的形态 (j) 与上一行的形态 (k) 的与运算结果为 (0)
        这样保证了上一行形态中为 (1) 的位对应的当前位一定为 (0),满足上述条件。
      • (j)(k) 的按位或运算的二进制表示中连续 (0) 的个数为偶数个。
        这样也就说明(j)(k) 的二进制表示中连续 (0) 的个数为偶数个。

      预处理合法(即连续 (0) 为偶数)的状态,然后 dp 即可。

      [f_{i,j}=sumlimits_{j&k=0且j|k合法}f_{i-1,k} ]

      #include <map>
      #include <cmath>
      #include <queue>
      #include <cstdio>
      #include <vector>
      #include <cstring>
      #include <iostream>
      #include <algorithm>
      #define ll long long
      using namespace std;
      
      const int A = 1e5 + 11;
      const int B = 1e6 + 11;
      const int mod = 1e9 + 7;
      const int inf = 0x3f3f3f3f;
      
      inline int read() {
        char c = getchar(); int x = 0, f = 1;
        for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
        for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
        return x * f;
      }
      
      int n, m;
      bool ok[A];
      ll f[12][1 << 11];
      
      int main() {
        while (cin >> n >> m) {
          if (n == 0 && m == 0) return 0;
          memset(f, 0, sizeof(f));
          for (int i = 0; i < (1 << m); i++) {
            bool cnt = 0, has_odd = 0;
            for (int j = 0; j < m; j++) 
              if (i >> j & 1) has_odd |= cnt, cnt = 0;
              else cnt ^= 1;
            ok[i] = !(has_odd | cnt);
          }
          f[0][0] = 1;
          for (int i = 1; i <= n; i++) {
            for (int j = 0; j < (1 << m); j++) {
              for (int k = 0; k < (1 << m); k++) 
                if ((j & k) == 0 && ok[j | k]) 
                  f[i][j] += f[i - 1][k];
            }
          }
          cout << f[n][0] << '
      ';
        }
      }
      
    • AcWing289 环路运输

      环形DP
      还是断环成链的操作
      把环拆开,复制一倍,形成一个长度为 (2n) 的链
      那么就是要求最大的 (1le{i,j}le{2n})({i-j}le{dfrac{n}{2}})(i,j)(a_i+a_j+i-j) 的最大值
      可以用单调队列优化,做到 (O(n)) 的复杂度

      #include <map>
      #include <cmath>
      #include <queue>
      #include <cstdio>
      #include <vector>
      #include <cstring>
      #include <iostream>
      #include <algorithm>
      using namespace std;
      
      const int A = 2e6 + 11;
      const int B = 1e6 + 11;
      const int mod = 1e9 + 7;
      const int inf = 0x3f3f3f3f;
      
      inline int read() {
        char c = getchar(); int x = 0, f = 1;
        for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
        for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
        return x * f;
      }
      
      int n, head, tail, len, a[A], q[A], ans;
      
      int main() {
        n = read();
        for (int i = 1; i <= n; i++) a[i] = read(), a[i + n] = a[i];
        len = n / 2, head = 1, tail = 0;
        q[++tail] = a[1];
        for (int i = 2; i <= n * 2; i++) {
          while (head <= tail && q[head] < i - len) head++;
          ans = max(ans, i + a[i] + a[q[head]] - q[head]);
          while (head <= tail && a[q[tail]] - q[tail] < a[i] - i) tail--;
          q[++tail] = i;
        }
        cout << ans << '
      ';
        return 0;
      }
      
    • 牛客编程巅峰赛S2第2场 - 钻石&王者T1
      函数式编程难受,机房电脑性能辣鸡

      class Solution {
      public:
          /**
           * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
           *
           * @param n long长整型 表示标准完全二叉树的结点个数
           * @return long长整型
           */
          long long tree4(long long n) {
              // write code here
              long long mod = 998244353;
              long long base = 0, x = 0, ans = 0;
              while (x + (1 << base) <= n) {
                  long long now = x + (1 << base);
                  ans = ans + (1ll * now * (now + 1) / 2 % mod - 1ll * x * (x + 1) / 2 % mod + mod) % mod * (base + 1);
                  ans = ans % mod;
                  x = now, base++;
              }
              if (x == n) return ans;
              ans += (1ll * n * (n + 1) / 2 % mod - x * (x + 1) / 2 % mod + mod) % mod * (base + 1) % mod;
              ans %= mod;
              return ans;
          }
      };
      
    • 牛客编程巅峰赛S2第2场 - 钻石&王者T2

      函数式编程难受,机房电脑性能辣鸡,不会写高精/kk

      class Solution {
        public:
          /**
           * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
           * 返回最大和的字符串
           * @param x string字符串 即题目描述中所给字符串
           * @param k int整型 即题目描述中所给的k
           * @return string字符串
           */
          string Maxsumforknumers(string x, int k) {
            int vis[100] = { 0 };
            int n = x.size(), ans[100001] = { 0 }, len = 0;
            string s;
            for (int i = 0; i < n; i++) vis[x[i] - '0']++;
            for (int i = 1; i <= n - k + 1; i++) {
              int we = 0;
              for (int j = 9; j >= 0; j--)
                if (vis[j]) {
                  we = j, vis[we]--;
                  break;
                }
              ans[i] = we;
            }
            len = n - k + 1;
            reverse(ans + 1, ans + len + 1);
            int we = 0;
            for (int j = 0; j <= 9; j++)
              while (vis[j]) {
                vis[j]--, we = j;
                int po = 1;
                ans[po] += j;
                while (ans[po] >= 10) ans[po] -= 10, po++, ans[po]++, len = max(len, po);
              }
            reverse(ans + 1, ans + len + 1);
            for (int i = 1; i <= len; i++) s += ans[i] + '0';
            return s;
          }
      };
      
    • AcWing292 炮兵阵地

      (f_{i,j,k}) 表示已经摆完前 (i) 行,且所有摆放的炮兵之间不能相互攻击到,每个炮兵都不在山地上,第 (i) 行的状态为 (j),第 (i-1) 行的状态为 (k) 的方案数。

      因为第 (i) 行和第 (i-1) 行的状态已经确定了,但是当前阶段还和第 (i-2) 行的状态有关,所以要枚举第 (i-2) 行的状态,记为 (u)

      什么时候状态是合法的呢?

      • (j,k,u) 三者表示的状态无交集。
      • (i) 行的炮兵没有摆放到山地上。
      • (i) 行的炮兵两两之间的距离(ge2)

      显然满足上述条件的状态就是合法的。

      转移: (f_{i,j,k}=f_{i-1,j,u}+sum_i)

      其中 (sum_i) 表示第 (i) 行可以摆放的炮兵的个数。

      #include <cmath>
      #include <queue>
      #include <cstdio>
      #include <vector>
      #include <cstring>
      #include <iostream>
      #include <algorithm>
      using namespace std;
      
      const int A = 111;
      const int B = 11;
      const int S = 1 << 11;
      const int mod = 1e9 + 7;
      const int inf = 0x3f3f3f3f;
      
      inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
        for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
        return x * f;
      }
      
      vector <int> sta;
      int n, m, g[A], sum[S], f[2][S][S];
      
      bool check(int s) {
        for (int i = 0; i < m; i++) 
          if (((s >> i) & 1) && (((s >> (i + 1)) & 1) || (s >> (i + 2) & 1)))
            return false;
        return true;
      }
      
      int count(int x) {
        int cnt = 0;
        while (x) {
          cnt += x & 1;
          x >>= 1;
        }
        return cnt;
      }
      
      int main() {
        n = read(), m = read();
        for (int i = 0; i < n; i++) {
          for (int j = 0; j < m; j++) {
            char c;
            cin >> c;
            if (c == 'H') g[i] += (1 << j);
          }
        }
        for (int i = 0; i < 1 << m; i++) {
          if (check(i)) {
            sta.push_back(i);
            sum[i] = count(i);
          }
        }
      //  cout << sta.size() << '
      ';
        for (int i = 0; i < n + 2; i++) {
          for (int k = 0; k < sta.size(); k++)
            for (int j = 0; j < sta.size(); j++)
              for (int u = 0; u < sta.size(); u++) {
                int a = sta[u], b = sta[j], c = sta[k];
                if ((a & b) || (a & c) || (b & c)) continue;
                if (g[i] & c) continue;
                f[i & 1][k][j] = max(f[i & 1][k][j], f[i - 1 & 1][j][u] + sum[c]);
              }
        }
        cout << f[n + 1 & 1][0][0] << '
      ';
      }
      
  • 相关阅读:
    接水果(fruit)——整体二分+扫描线
    大融合——LCT维护子树信息
    魔卡少女(cardcaptor)——线段树
    而立之年的一些人生感悟
    PHP 输出缓冲控制(Output Control) 学习
    我所了解的cgi
    c语言指针学习
    ubuntu 安装 zend studio
    Zend_Controller_Front 研究
    php autoload 笔记
  • 原文地址:https://www.cnblogs.com/loceaner/p/13994810.html
Copyright © 2011-2022 走看看