目录

noip模拟39

打地鼠-竞赛图-糖果-树

T1 打地鼠

过水,考场上有一车人切掉

T2 竞赛图

状压思想的神仙题目,通过不断消去最后以为的方式去枚举子集

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <bits/stdc++.h>
#define For(i, l, r) for (long long i = (l), i##end = (r); i <= i##end; ++i)
#define Fordown(i, r, l) for (long long i = (r), i##end = (l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;
const long long maxn = 16777217;

template<typename type>
type read() {
  type s = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    s = s * 10 + ch - '0';
    ch = getchar();
  }
  return s * f;
}


int lowbit(int x) {
  return x & (-x);
}

bool vis[maxn];
int m[maxn];

int n;
int main() {
  int t;
  t = read<int>();
  while (t--) {
    Set(m, 0);
    Set(vis, 1);
    int n;
    n = read<int>();
    For(i, 1, n) {
      For(j, 1, n) {
        int x;
        x = read<int>();
        if (x) {
          m[(1 << (i - 1))] |= (1 << (j - 1));
        }
      }
    }
    int maxs = (1 << n) - 1;
    m[0] = maxs;
    For(state, 1, maxs) {
      m[state] = m[state ^ lowbit(state)] & m[lowbit(state)];
    }
    For(state, 1, maxs) {
      if (vis[state]) {
        for (int j = m[state]; j; j = (j - 1) & m[state]) {
          vis[state | j]  = 0;
        }
      }
    }
    int ans = 0;
    For(state, 0, maxs) {
      if (vis[state]) {
        ans++;
      }
    }
    cout << ans << endl;
  }
  return 0;
}

T3 糖果

神仙dp题

在小A和小B选数的过程中,限制有:小A和小B不能选到同一个数。对于某一个数,小A和小B经过时都没有选它,那么它之前必然已经被小C选过了。因此可以使用dp[i][j][k]表示在某一轮,小A选了第i个位置上的数,小B选了第j个位置上的数,还有k的不确定的位置(小C)因为i和j两维可以分开转移转移只需枚举i和j,若i(j) + 1位置上的数已经被选了,就换一维转移。


一些转移的细节: 转移i时:

如果当前的数a[i]在b中的位置小于j,即被选过了, 就把它删掉,状态给下一个位置

如果k不等于0,就确定下来一个k

转移j时同理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <bits/stdc++.h>
#define For(i, l, r) for (long long i = (l), i##end = (r); i <= i##end; ++i)
#define Fordown(i, r, l) for (long long i = (r), i##end = (l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;
const long long maxn = 410;
const long long mod = 1e9 + 7;

template<typename rsp5u>
rsp5u read() {
  rsp5u s = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    s = s * 10 + ch - '0';
    ch = getchar();
  }
  return s * f;
}

long long min(long long a, long long b) {
  return (a < b) ? a : b;
}

long long dp1[maxn][maxn][maxn], dp2[maxn][maxn][maxn];
long long a[maxn], b[maxn];
long long posa[maxn], posb[maxn];

long long n;
int32_t main() {
  n = read<long long>();
  long long n3 = n / 3;
  long long ans = 0;
  For(i, 1, n) {
    long long in;
    a[i] = read<long long>();
    posa[a[i]] = i;
  }
  For(i, 1, n) {
    long long in;
    b[i] = read<long long>();
    posb[b[i]] = i;
  }
  dp1[1][1][0] = 1;
  For(i, 1, n + 1) {
    For(j, 1, n + 1) {
      For(k, 0, n / 3) {
        if (dp1[i][j][k]) {
          //cout << dp1[i][j][k] << " |1 "<< ' ' << i << ' ' << j << ' ' << k  << endl;
          if (i != n + 1) {
            if (posb[a[i]] < j) { // deleted
              dp1[i + 1][j][k] += dp1[i][j][k];
              dp1[i + 1][j][k] %= mod;
            } else {
              if (k) {
                dp1[i + 1][j][k - 1] += dp1[i][j][k] * k;
                dp1[i + 1][j][k - 1] %= mod;
              }
              dp2[i][j][k] += dp1[i][j][k];
              dp2[i][j][k] %= mod;
            }
          } else {
            if (k == 0) {
              ans += dp1[i][j][0];
              ans %= mod;
            }
          }
        }
        if (dp2[i][j][k]) {
          //cout << dp2[i][j][k] << " |2 "<< ' ' << i << ' ' << j << ' ' << k  << endl;
          if (posa[b[j]] < i) { // deleted
            dp2[i][j + 1][k] += dp2[i][j][k];
            dp2[i][j + 1][k] %= mod;
          } else {
            if (a[i] != b[j]) {
              if (k) {
                dp2[i][j + 1][k - 1] += dp2[i][j][k] * k;
                dp2[i][j + 1][k - 1] %= mod;
              }
              dp1[i + 1][j + 1][k + 1] += dp2[i][j][k];
              dp1[i + 1][j + 1][k + 1] %= mod;
            }
          }
        }
      }
    }
  }
  ans %= mod;
  For(i, 1, n3) {
    ans = ans * (3 * i -1) * (3 * i - 2);
    ans %= mod;
  }
  cout << ans << endl;
  return 0;
}
`