#8:二日合辑——6

时间:2022-03-13 22:17:47

BZOJ1001,裸网络流,对偶图做法比较有趣但在这道题上好像有点花哨?

#8:二日合辑——6#8:二日合辑——6
  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 }
View Code

 

BZOJ1004,刻骨铭心的burnside。

#8:二日合辑——6#8:二日合辑——6
 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 }
View Code

 

UVa10294,polya的基本应用题。

#8:二日合辑——6#8:二日合辑——6
 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 }
View Code

 

UVALive3641,有置换的结论,对于置换A²,循环节奇数长度相乘还是原长,偶数长度相乘分裂为原来的一半相乘。

#8:二日合辑——6#8:二日合辑——6
 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 }
View Code

 

UVa11077,一是找到“交换即在同一置换循环节里”这一本质,二是递推。私以为蓝书递推解释错了,但代码是对的。f[i-1][j-1]代表了循环节个数不变还是i-j个但是这些循环节加起来共有i-1个位置可供i去放所以乘i-1;还有一种情况就是i-1-j个循环节然后i独立成节。

#8:二日合辑——6#8:二日合辑——6
 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 }
View Code

 

UVALive3510,循环节lcm常见操作,but这波图像模拟真是emmmmm……

#8:二日合辑——6#8:二日合辑——6
 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 }
View Code