BZOJ1001,裸网络流,对偶图做法比较有趣但在这道题上好像有点花哨?
1 #include <bits/stdc++.h> 2 #define ri readint() 3 #define wi(x) writeint(x) 4 #define gc getchar() 5 #define pc(x) putchar(x) 6 #define rep(i, a, b) for (int i = a; i <= b; i++) 7 #define init(a, b) memset(a, b, sizeof(a)) 8 using namespace std; 9 10 const int inf = 1e9; 11 const int maxn = 1e6 + 5; 12 const int maxm = 6e6 + 1e4; 13 14 struct Edge { 15 int to, cost, nxt; 16 }e[maxm]; 17 int head[maxn], d[maxn], tot = 1; 18 int n, m, st, ed; 19 queue<int> Q; 20 21 inline int readint() { 22 int x = 0, s = 1, c = gc; 23 while (c <= 32) c = gc; 24 if (c == '-') s = -1, c = gc; 25 for (; isdigit(c); c = gc) 26 x = x * 10 + c - 48; 27 return x * s; 28 } 29 30 inline void writeint(int x) { 31 if (x > 9) writeint(x/10); 32 pc(x%10 + 48); 33 } 34 35 inline void add(int x, int y, int z) { 36 e[++tot].to = y, e[tot].cost = z, e[tot].nxt = head[x], head[x] = tot; 37 e[++tot].to = x, e[tot].cost = z, e[tot].nxt = head[y], head[y] = tot; 38 } 39 40 bool bfs() { 41 init(d, 0); 42 while (Q.size()) Q.pop(); 43 44 Q.push(st), d[st] = 1; 45 while (Q.size()) { 46 int x = Q.front(); Q.pop(); 47 for (int i = head[x]; i; i = e[i].nxt) { 48 if (e[i].cost && !d[e[i].to]) { 49 Q.push(e[i].to); 50 d[e[i].to] = d[x] + 1; 51 if (e[i].to == ed) return true; 52 } 53 } 54 } 55 56 return false; 57 } 58 59 int dinic(int x, int flow) { 60 if (x == ed) return flow; 61 int rest = flow; 62 for (int i = head[x]; i && rest; i = e[i].nxt) { 63 if (e[i].cost && d[e[i].to] == d[x] + 1) { 64 int k = dinic(e[i].to, min(rest, e[i].cost)); 65 if (!k) d[e[i].to] = 0; 66 e[i].cost -= k; 67 e[i ^ 1].cost += k; 68 rest -= k; 69 } 70 } 71 72 return flow - rest; 73 } 74 75 int solve() { 76 int maxflow = 0; 77 st = 1, ed = n * m; 78 while (bfs()) maxflow += dinic(st, inf); 79 return maxflow; 80 } 81 82 int main() { 83 n = ri, m = ri; 84 rep(i, 1, n) 85 rep(j, 1, m-1) { 86 int c = ri; 87 int x = (i-1)*m+j, y = x+1; 88 add(x, y, c); 89 } 90 rep(i, 1, n-1) 91 rep(j, 1, m) { 92 int c = ri; 93 int x = (i-1)*m+j, y = i*m+j; 94 add(x, y, c); 95 } 96 rep(i, 1, n-1) 97 rep(j, 1, m-1) { 98 int c = ri; 99 int x = (i-1)*m+j, y = i*m+j+1; 100 add(x, y, c); 101 } 102 103 wi(solve()); 104 return 0; 105 }
BZOJ1004,刻骨铭心的burnside。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 typedef long long ll; 9 int Sr, Sb, Sg, m, p; 10 int n, C[65], ans; 11 int f[25][25][25]; 12 vector<int> Equal; 13 bool mark[65]; 14 15 int cal() { 16 memset(mark, false, sizeof(mark)); 17 memset(f, 0, sizeof(f)); 18 Equal.clear(); 19 20 for (int i = 1; i <= n; i++) { 21 if (!mark[i]) {//如果还不属于某个循环节 22 int k = 0; 23 for (int j = i; !mark[j]; j = C[j]) { 24 mark[j] = true; 25 k++; 26 } 27 Equal.push_back(k);//这个循环节里共有多少个元素 28 } 29 } 30 31 f[0][0][0] = 1; 32 for (int i = 0; i < Equal.size(); i++)//枚举每个循环节 33 for (int jr = Sr; ~jr; jr--) 34 for (int jb = Sb; ~jb; jb--) 35 for (int jg = Sg; ~jg; jg--) { 36 int size = Equal[i]; 37 if (size <= jr) 38 f[jr][jb][jg] = (f[jr][jb][jg] + f[jr - size][jb][jg]) % p; 39 if (size <= jb) 40 f[jr][jb][jg] = (f[jr][jb][jg] + f[jr][jb - size][jg]) % p; 41 if (size <= jg) 42 f[jr][jb][jg] = (f[jr][jb][jg] + f[jr][jb][jg - size]) % p; 43 } 44 return f[Sr][Sb][Sg]; 45 } 46 47 int ksm(int a, int b, int mod) { 48 int res = 1; 49 for (; b; b >>= 1) { 50 if (b & 1) res = (ll)res * a % mod; 51 a = (ll)a * a % mod; 52 } 53 return res; 54 } 55 56 int main() { 57 cin >> Sr >> Sb >> Sg >> m >> p; 58 n = Sr + Sb + Sg; 59 60 for (int i = 1; i <= m; i++) {//每个置换 61 for (int i = 1; i <= n; i++) 62 cin >> C[i]; 63 ans = (ans + cal()) % p; 64 } 65 for (int i = 1; i <= n; i++)//单位元置换 66 C[i] = i;//e * e = e,即完全不动 67 ans = (ans + cal()) % p; 68 69 cout << ans * ksm(m+1, p-2, p) % p << endl;//(ans/(m+1))%p 70 return 0; 71 }
UVa10294,polya的基本应用题。
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 int n, t; 6 ll Pow[51], a, b; 7 8 int main() { 9 while (~scanf("%d%d", &n, &t)) { 10 Pow[0] = 1ll; 11 for (int i = 1; i <= n; i++) 12 Pow[i] = Pow[i-1] * t; 13 14 a = 0ll; 15 for (int i = 1; i <= n; i++)//转n个就是没转 16 a += Pow[__gcd(i, n)]; 17 18 if (n & 1) b = n * Pow[n/2 + 1]; 19 else b = n / 2 * (Pow[n/2 + 1] + Pow[n/2]); 20 21 printf("%lld %lld\n", a / n, (a+b) / (2*n)); 22 } 23 return 0; 24 }
UVALive3641,有置换的结论,对于置换A²,循环节奇数长度相乘还是原长,偶数长度相乘分裂为原来的一半相乘。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int T; 5 char S[27]; 6 int cnt[27]; 7 bool vis[26]; 8 9 int main() { 10 for (cin >> T; T; T--) { 11 cin >> S; 12 memset(vis, 0, sizeof(vis)); 13 memset(cnt, 0, sizeof(cnt)); 14 15 for (int i = 0; S[i]; i++) { 16 if (!vis[i]) { 17 int k = 0; 18 for (int j = i; !vis[j]; j = S[j] - 'A') { 19 k++; 20 vis[j] = true; 21 } 22 cnt[k]++; 23 } 24 } 25 26 bool flag = true; 27 for (int i = 2; i <= 26; i += 2) 28 if (cnt[i] & 1) 29 flag = false; 30 31 if (flag) puts("Yes"); 32 else puts("No"); 33 } 34 return 0; 35 }
UVa11077,一是找到“交换即在同一置换循环节里”这一本质,二是递推。私以为蓝书递推解释错了,但代码是对的。f[i-1][j-1]代表了循环节个数不变还是i-j个但是这些循环节加起来共有i-1个位置可供i去放所以乘i-1;还有一种情况就是i-1-j个循环节然后i独立成节。
1 #include <bits/stdc++.h> 2 #define ull unsigned long long 3 using namespace std; 4 5 int n, k; 6 ull f[25][25]; 7 8 int main() { 9 for (int i = 1; i <= 21; i++) { 10 f[i][0] = 1; 11 for (int j = 1; j < i; j++) { 12 f[i][j] = f[i-1][j] + f[i-1][j-1] * (i-1); 13 } 14 } 15 16 while (~scanf("%d%d", &n, &k) && n) { 17 printf("%llu\n", f[n][k]); 18 } 19 return 0; 20 }
UVALive3510,循环节lcm常见操作,but这波图像模拟真是emmmmm……
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 1 << 10; 5 int n, n2, T; 6 int cur[maxn*maxn], ogri[maxn*maxn]; 7 bool vis[maxn*maxn]; 8 9 inline int id(int i, int j) { 10 return i * n + j; 11 } 12 13 int Newid(int i, int j, const char *op) { 14 if (op[0] == 'i') 15 return id(i, j); 16 else if (op[0] == 'r') 17 return id(n-1-j, i); 18 else if (op[0] == 's') 19 return id(i, n-1-j); 20 else if (op[0] == 'b' && op[1] == 'h') 21 return i < n/2 ? id(i, j) : id(i, n-1-j); 22 else if (op[0] == 'b' && op[1] == 'v') 23 return i < n/2 ? id(i, j) : id(n/2+n-i-1, j); 24 else if (op[0] == 'd') 25 return i & 1 ? id(n/2+i/2, j) : id(i/2, j); 26 else { 27 int k = i/2; 28 if (j < n/2) 29 return i & 1 ? id(2*k, 2*j+1) : id(2*k, 2*j); 30 else 31 return i & 1 ? id(2*k+1, 2*(j-n/2)+1) : id(2*k+1, 2*(j-n/2)); 32 } 33 } 34 35 void Apply(const char *op) { 36 bool inv = op[strlen(op)-1] == '-'; 37 for (int i = 0; i < n*n; i++) ogri[i] = cur[i]; 38 for (int i = 0; i < n; i++) 39 for (int j = 0; j < n; j++) { 40 int p = id(i, j), p2 = Newid(i, j, op); 41 if (inv) cur[p] = ogri[p2]; 42 else cur[p2] = ogri[p]; 43 } 44 } 45 46 inline int __lcm(int a, int b) { 47 return a / __gcd(a, b) * b; 48 } 49 50 int Solve(int m) { 51 memset(vis, 0, sizeof(vis)); 52 int ans = 1; 53 for (int i = 0; i < m; i++) { 54 if (!vis[i]) { 55 int len = 0; 56 for (int j = i; !vis[j]; j = cur[j]) { 57 vis[j] = true; 58 len++; 59 } 60 ans = __lcm(ans, len); 61 } 62 } 63 return ans; 64 } 65 66 int main() { 67 for (scanf("%d%d", &T, &n); T--; n = n2) { 68 for (int i = 0; i < n*n; i++) 69 cur[i] = i; 70 string s; 71 vector<string> v; 72 while (cin >> s) { 73 if (isdigit(s[0])) { 74 sscanf(s.c_str(), "%d", &n2); 75 break; 76 } 77 v.push_back(s); 78 } 79 for (int i = v.size()-1; ~i; i--) { 80 Apply(v[i].c_str()); 81 } 82 83 printf("%d\n", Solve(n*n)); 84 if (T) puts(""); 85 } 86 return 0; 87 }