「csp模拟」模拟测试15

T1:阴阳

  • 正解不会。。。

60分暴力代码

#include <bits/stdc++.h>
using namespace std;
#define cle(a) memset(a, 0, sizeof(a))
inline int read() {
    int k = 0, f = 1; char ch = getchar();
    for (; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    for (; isdigit(ch); ch = getchar()) k = k * 10 + ch - '0';
    return k * f;
}
const int mod = 1e9 + 7, maxn = 1e3 + 100;
int n, m, ans = 0;
int f[maxn][maxn];
int jl[maxn][maxn], a[maxn][maxn];
int jlh1b[6], jll1b[6];
int jlh2b[6], jll2b[6];
int jlh1e[6], jll1e[6];
int jlh2e[6], jll2e[6];
int vis[6][6];
void dfs1(int x, int y, int col) {
    if (x < 1 || y < 1 || x > n || y > m || vis[x][y] == 1) return;
    if (jl[x][y] == col) {
        vis[x][y] = 1;
        dfs1(x + 1, y, col);
        dfs1(x, y + 1, col);
        dfs1(x - 1, y, col);
        dfs1(x, y - 1, col);
    }
}
void dfs(int cur, int cnt) {
    if (cur == n * m + 1) {
        cle(jlh1b), cle(jll1b);
        cle(jlh2b), cle(jll2b);
        cle(jlh1e), cle(jll1e);
        cle(jlh2e), cle(jll2e);
        memset(vis, 0, sizeof(vis));
        for (int i = 1; i <= n; i++) {
            int flag = 0;
            for (int j = 1; j <= m; j++) {
                if (jl[i][j] == 1) jlh1e[i] = j;
                if (jl[i][j] == 2) jlh2e[i] = j;
                if (jl[i][j] == 1) jll1e[j] = i;
                if (jl[i][j] == 2) jll2e[j] = i;        
                if (jl[i][j] == 1 && jlh1b[i] == 0) jlh1b[i] = j;
                if (jl[i][j] == 2 && jlh2b[i] == 0) jlh2b[i] = j;
                if (jl[i][j] == 1 && jll1b[j] == 0) jll1b[j] = i;
                if (jl[i][j] == 2 && jll2b[j] == 0) jll2b[j] = i;
            }
        }
        int now = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (!vis[i][j]) dfs1(i, j, jl[i][j]), now++;
                if (now > 2) return ;
            }
        }
        int col = jl[1][1];
        int line = 1, row = 1;
        for (int i = 1; i <= m; i++) {
            if (jll1b[i] == 0) continue;
            if (jll2b[i] == 0) continue;    
            for (int j = jll1b[i]; j <= jll1e[i]; j++) if (jl[j][i] != 1) return;
            for (int j = jll2b[i]; j <= jll2e[i]; j++) if (jl[j][i] != 2) return;
        }
        for (int i = 1; i <= n; i++) {
            if (jlh1b[i] == 0) continue;
            if (jlh2b[i] == 0) continue;            
            for (int j = jlh1b[i]; j <= jlh1e[i]; j++) if (jl[i][j] != 1) return;
            for (int j = jlh2b[i]; j <= jlh2e[i]; j++) if (jl[i][j] != 2) return;
        }
        ans ++;
        ans %= mod;
        return;
    }
    int row = cur % m, line = cur / m + 1;
    if (row == 0) row = m;
    if (cur % m == 0) line--;
    if (a[line][row] == 1) dfs(cur + 1, cnt);
    else if (a[line][row] == 2) dfs(cur + 1, cnt + 1);
    else {
        jl[line][row] = 1; dfs(cur + 1, cnt); jl[line][row] = 0;
        jl[line][row] = 2; dfs(cur + 1, cnt + 1); jl[line][row] = 0;
    }
}
signed main() {
    freopen("yinyang.in", "r", stdin), freopen("yinyang.out", "w", stdout);
    n = read(), m = read();
    int cnt = 0, cnt1 = 0;
    for (int i = 1; i <= n; i++) {
        char s[maxn]; scanf("%s", s + 1);
        for (int j = 1; j <= m; j++) {
            if (s[j] == 'B') a[i][j] = jl[i][j] = 1, cnt1 ++;
            else if (s[j] == 'W') a[i][j] = jl[i][j] = 2, cnt++;
            else a[i][j] = 3;
        }
    }
    if (m < 5 && n < 5) return dfs(1, 0), cout << ans << endl, 0;
    for (int i = 1; i <= n; i++) f[i][1] = i * 2;
    for (int i = 1; i <= m; i++) f[1][i] = i * 2;
    for (int i = 2; i <= n; i++)
        for (int j = 2; j <= m; j++) 
            f[i][j] = (f[i - 1][j] + f[i][j - 1] + (i + j - 1) * 2) % mod;
    cout << f[n][m] % mod << endl;
}

T2:简单的序列

dp,第一位表示左面的长度,第二位表示左面的左括号数目,具体解析见代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read() {
    int k = 0, f = 1; char ch = getchar();
    for (; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    for (; isdigit(ch); ch = getchar()) k = k * 10 + ch - '0';
    return k * f;
}
const int mod = 1e9 + 7, maxn = 1e6 + 1000;
int jc[maxn], ny[maxn], jcny[maxn];
inline int qpow(int x, int y) {
    int ans = 1;
    for (; y; y >>= 1, x = x * x % mod) if (y & 1) ans = ans * x % mod;
    return ans;
}
int C(int n, int m) {   
    return jc[n] * jcny[m] % mod * jcny[n - m] % mod;
}
signed main() {
    freopen("bracket.in", "r", stdin), freopen("bracket.out", "w", stdout);
    jc[0] = ny[0] = ny[1] = jcny[0] = jcny[1] = 1;
    int n = read(), m = read();
    for (int i = 1; i <= n; i++) jc[i] = jc[i - 1] * i % mod;
    for (int i = 2; i <= n; i++) ny[i] = (mod - mod / i) * ny[mod % i] % mod;
    for (int i = 2; i <= n; i++) jcny[i] = jcny[i - 1] * ny[i] % mod;
    char s[maxn]; scanf("%s", s + 1);
    int tot = 0, maxx = 0, cntl = 0, cntr = 0;
    for (int i = 1; i <= m; i++) {
        if (s[i] == '(') tot --, cntl ++;
        if (s[i] == ')') tot ++, cntr ++;
        if (tot > maxx) maxx = tot;
    }
    int ans = 0;
    for (int i = 0; i <= n - m; i++) {
        for (int j = (i + maxx + 1) / 2; j <= i; j++) {
            int now = cntl + j;
            int cur = n / 2 - now; // 右边的左括号数目,即向上走的步数
            ans = (ans + ((C(i, j) - C(i, j + 1) + mod) % mod) * ((C(n - i - m, cur) - C(n - i - m, cur - 1) + mod) % mod) % mod) % mod;            
            // (C(i, j) - C(i, j + 1) + mod) % mod) : 左边在 i 的长度中选择 j 个左括号的方案数目, 坐标系上起点为(0, 0),终点为 (i, (j - (i - j))) => (i, 2 * j - i) ,关于 ( y = -1 )的对称点为 (i, i - 2 * j - 2),
            // 令 x 为向下走的步数,则 (i - x) 为向上走的步数,所以 (x - (i - x)) == (i - 2 * j - 2), 解得 x = (j + 1),所以左边方案数即可得。
            // (C(n - i - m, cur) - C(n - i - m, cur - 1) : cur 为右边要选择的左括号数目,(总共 n/2 个左括号,左边一共有了 (cntl + j) 个左括号),起点为 (0, 一个数),终点为(n - m - i, 0), 对称点为 (n - m - i, -2), 
            // 从其中选择 cur 步往上走, 则有 (n - i - m - cur) 步往下走, 所以起点为 (0, n - i - m - cur - cur) 终点为 (n - i - m, -2), 还是令向上走的步数为 x, 
            // 所以 (x - (n - i - m - x)) == (0, -2 - n + i + m + 2 * cur) , 解得 x = (cur - 1), 所以右边方案数就知道了,最后左边乘右边就对了。。。
        }
    }
    cout << ans % mod << endl;
}

T3:简单的期望

正解dp,转移很复杂,这里只给出暴力代码,要打好概率dp的暴力!!!

#include <bits/stdc++.h>
using namespace std;
#define int long long
inline int read() {
    int k = 0, f = 1; char ch = getchar();
    for (; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    for (; isdigit(ch); ch = getchar()) k = k * 10 + ch - '0';
    return k * f;
}
int x, n; double p, ans;
void dfs(int cnt, double now, double cur) {
    if (cnt == n) {
        int curans = 0;
        int x = (int)now;   
        while (x % 2 == 0) curans ++, x /= 2;
        ans += 1.0 * curans * cur;
        return;
    }
    dfs(cnt + 1, now * 2, cur * p);
    dfs(cnt + 1, now + 1, cur * (1 - p));
}
signed main() {
    freopen("exp.in","r",stdin), freopen("exp.out","w",stdout);
    x = read(), n = read(); p = 1.0 * read() / 100;
    dfs(0, x, 1);
    printf("%.10lf
", ans);
    return 0;
}

T4:简单的操作

原文地址:https://www.cnblogs.com/hellohhy/p/13832592.html