11.8校内测试倒计时2天状压DP随机化?/暴力小模拟
Posted wans-caesar-02111007
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了11.8校内测试倒计时2天状压DP随机化?/暴力小模拟相关的知识,希望对你有一定的参考价值。
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随机化?/暴力小模拟的主要内容,如果未能解决你的问题,请参考以下文章