码迷,mamicode.com
首页 > 其他好文 > 详细

【11.8校内测试】【倒计时2天】【状压DP】【随机化?/暴力小模拟】

时间:2018-11-08 18:14:35      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:margin   turn   转移   这一   ini   out   memset   mod   using   

技术分享图片

Solution

数据范围疯狂暗示状压,可是一开始发现状态特别难受。

将每一层的奇偶性状压,预处理所有状态的奇偶性。每一层的输入代表的其实可以是下一层某个点可以被从这一层哪些点转移到。

所以枚举每个状态,再枚举下一层转移到哪个点,统计这个点被这个状态更新的话正边和反边分别的奇偶性,转移即可。

第二层和最后一层单独处理即可。

Code

#include<bits/stdc++.h>
#define mod 998244353
using namespace std;

int x, dp[2][(1 << 11)], pre[(1 << 11)], up[1 << 11], dn[1 << 11];
int m, k;

int read () {
    int x = 0, f = 0; char c = getchar ();
    while (!isdigit (c)) f |= (c == -), c = getchar ();
    while (isdigit (c)) x = x * 10 + c - 0, c = getchar ();
    return f ? -x : x;
}

void init() {
    for(int i = 0; i < (1 << k); i ++)
        pre[i] = (i & 1) ^ pre[i >> 1];
}

int main() {
    freopen("adore.in", "r", stdin);
    freopen("adore.out", "w", stdout);
    scanf("%d%d", &m, &k);
    int sta = 0;
    for(int i = 0; i < k; i ++)    {
        x = read(),    sta |= (x << i);
    }
    dp[0][sta] = 1; init(); 
    int now = 0;
    for(int i = 1; i < m - 2; i ++) {
        now ^= 1;
        memset(dp[now], 0, sizeof(dp[now]));
        memset(up, 0, sizeof(up));
        memset(dn, 0, sizeof(dn));
        for(int u = 0; u < k; u ++)
            for(int v = 0; v < k; v ++) {
                x = read();
                up[u] |= (x << v);////反边 u能被那些点更新过来 
                dn[v] |= (x << u);////正边 
            }
        for(int s = 0; s < (1 << k); s ++)
            if(dp[now ^ 1][s]) {
                int A = 0, B = 0;
                for(int j = 0; j < k; j ++)
                    A |= ((pre[s & up[j]]) << j), B |= ((pre[s & dn[j]]) << j);
                dp[now][A] = (dp[now][A] + dp[now ^ 1][s]) % mod;
                dp[now][B] = (dp[now][B] + dp[now ^ 1][s]) % mod;
            }
    }
    int st = 0;
    for(int i = 0; i < k; i ++)    x = read(), st |= (x << i);
    int ans = 0;
    for(int s = 0; s < (1 << k); s ++)
        if(!pre[st & s])    ans = (ans + dp[now][s]) % mod;
    printf("%d", ans);
    return 0;
}

技术分享图片

技术分享图片

Solution

!!!原来是有$n+1$排!!是说为什么每次闪退QAQ

其实就是小模拟,直接三层for循环找到答案退出即可QAQ这个复杂度太有欺骗性了!!

其实随机搞更快???

Code

#include<bits/stdc++.h>
using namespace std;

int n, t1, t2, num[6005];
string s;
bitset < 12005 > b[6005];

int main() {
    freopen("confess.in", "r", stdin);
    freopen("confess.out", "w", stdout);
    srand(time(0));
    scanf("%d", &n);
    for(int i = 0; i <= n; i ++) {
        cin >> s;
        int len = s.length();
        for(int j = 0; j < len; j ++) {
            int a = s[j] - 33;
            for(int k = 5; k >= 0; k --)if(num[i]<(n<<1))    b[i][++num[i]] = ((a >> k) & 1);
        }
    }
    int cnt;
    while(1) {
        int i = rand() % (n + 1);
        int j = rand() % (n + 1);
        if(i == j) j ++;
        if((b[i] & b[j]).count() >= (n / 2)) {
            if(i > j)    swap(i, j);
            printf("%d %d", i+1, j+1); return 0;
        }
    }
    printf("NO Solution");
    return 0;
}

 

【11.8校内测试】【倒计时2天】【状压DP】【随机化?/暴力小模拟】

标签:margin   turn   转移   这一   ini   out   memset   mod   using   

原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/9929774.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!