ZOJ Monthly, January 2008解题报告

ZOJ Monthly, January 2008解题报告
2894        Arrange the Problem Set     
 
2895       Cache       Recommended
首先我们用1000大的cache,这样次数最少。
然后我们试着用更小的cache来达到同样的效果。
注意到对两个地址i和j,如果他们的request区间有overlap,那么所满足i % n == j % n的n就不能用作cache大小。
然后我们就把所有不合法的cache size标记,寻找最小的~
注意n == 0的时候输出0,-_-bbbbbbbb
CODE
 1//    ZOJ Monthly, January 2008, Cache 
 2//    Written By FreePeter
 3
 4#include <cstdio>
 5#include <cstring>
 6#include <iostream>
 7#include <algorithm>
 8
 9using namespace std;
10
11const int MaxN = 1000000 + 10;
12pair<intint> occur[1000];
13int s[MaxN], n;
14bool mark[1010];
15
16void init();
17void work();
18void mark_factor(int x);
19
20int main() {
21    for (; scanf("%d"&n) != EOF; ) {
22        init();
23        work();
24    }

25
26    return 0;
27}

28
29void init() {
30    fill(occur, occur + 1000, make_pair(n + 1-1));
31    for (int i = 0; i < n; ++i) {
32        scanf("%d"&s[i]);
33        occur[s[i]].first <?= i;
34        occur[s[i]].second >?= i;
35    }

36}

37
38void work() {
39    if (n == 0{
40        cout << 0 << endl; return;
41    }

42
43    fill(mark, mark + 1010false);
44    for (int i = 0; i < 1000++i)
45        for (int j = i + 1; j < 1000++j) {
46            if (occur[i].second < occur[j].first || occur[j].second < occur[i].first) continue;
47            
48            mark[1= true; mark_factor(j - i);
49        }

50
51    int ans = 1
52    for (; mark[ans]; ) ++ans;
53    cout << ans << endl;
54}

55
56void mark_factor(int x) {
57    if (mark[x]) return;
58    mark[x] = true;
59    for (int i = 2; i * i <= x; ++i) {
60        if (x % i) continue;
61        mark_factor(i); mark_factor(x / i);
62    }

63}

64
65
66


2896       Common Factor       Recommended
在一个素数域上考虑这个问题,那么他们的Common Factor可以通过GCD求出来。
然后测试一些大素数,如果都通过了就可以认为他们存在Common Factor了。

2897       Desmond's Ambition    Recommended
首先求出所有的桥,如果将那些block视为一个点那么图就成为一棵树。
接下来分为4部分求:(建议自己想想,这个不太容易描述)
1. 每块内部的距离,暴力。
2. 每个桥被使用的次数,其实就是桥左边的顶点数*桥右边的顶点数,在DFS的时候顺便计算即可,参考 Bridges
3. 每块内部的点对的最短路被经过的次数,对(u, v)点对来说,就是f(u)*f(v)*dist(u,v)
f(u)定义为,列举出所有一个顶点在u上的桥,在桥的令一端的顶点个数和。
4. 每块内部点通过某个点和外界联系的距离和。f(u) * sum_dist(u),sum_dist(u)是u到同一块内的其他所有点的最短距离和。
CODE
  1//    ZOJ Monthly, January 2008, Desmond's Ambition
  2//    Written By FreePeter
  3
  4#include <cstdio>
  5#include <cstring>
  6#include <iostream>
  7#include <vector>
  8
  9using namespace std;
 10
 11const int MaxN = 10000 + 10, MaxEN = 100000 + 10;
 12struct EdgeNode {
 13    int p, len, id;
 14}
;
 15vector<EdgeNode> g[MaxN];
 16vector<EdgeNode> tree[MaxN];
 17vector<int> block[MaxN];
 18int n, m, color[MaxN], sum[MaxN], block_cnt;
 19long long ans;
 20long long f1[MaxN], f2[MaxN];
 21bool vis[MaxN], is_bridge[MaxEN];
 22int bridge[MaxEN], bridge_cnt;
 23int edge[MaxEN][3];
 24int low[MaxN], depth[MaxN], dfs_color[MaxN];
 25
 26void init();
 27void work();
 28void dfs_bridge(int u, int fa, int deep);
 29void dfs_tree(int u, int fa);
 30void dfs_block(int u, int fa, int block_id);
 31void generate_block_dist(int idx);
 32long long gcd(long long a, long long b);
 33
 34int main() {
 35    for (; scanf("%d%d"&n, &m) != EOF; ) {
 36        init();
 37        work();
 38    }

 39    return 0;
 40}

 41
 42void init() {
 43    for (int i = 0; i < n; ++i) {
 44        g[i].clear(); tree[i].clear(); block[i].clear();
 45    }

 46    for (int i = 0; i < m; ++i) {
 47        int a, b, c;
 48        scanf("%d%d%d"&a, &b, &c);
 49        --a; --b;
 50        EdgeNode tmp;
 51        tmp.p = b; tmp.len = c; tmp.id = i;
 52        g[a].push_back(tmp);
 53        tmp.p = a;
 54        g[b].push_back(tmp);
 55        edge[i][0= a; edge[i][1= b; edge[i][2= c;
 56    }

 57}

 58
 59void work() {
 60    //    Generate all the bridges
 61    fill(is_bridge, is_bridge + m, false);
 62    fill(dfs_color, dfs_color + n, 0);
 63    bridge_cnt = 0;
 64    dfs_bridge(0-10);
 65
 66    //    Generate all the blocks
 67    fill(vis, vis + n, false);
 68    block_cnt = 0;
 69    for (int i = 0; i < n; ++i)
 70        if (!vis[i]) {
 71            dfs_block(i, -1, block_cnt);
 72            ++block_cnt;
 73        }

 74
 75    //    Generate the Tree
 76    fill(f1, f1 + n, 0); fill(f2, f2 + n, 0);
 77    for (int i = 0; i < bridge_cnt; ++i) {
 78        int eid = bridge[i];
 79        int a = edge[eid][0], b = edge[eid][1], c = edge[eid][2];
 80        int aa = color[a], bb = color[b];
 81        EdgeNode tmp;
 82        tmp.p = bb; tmp.len = c; tmp.id = eid;
 83        tree[aa].push_back(tmp);
 84        tmp.p = aa;
 85        tree[bb].push_back(tmp);
 86
 87    //    f1[a] += block[bb].size(); f1[b] += block[aa].size();
 88    }

 89
 90    ans = 0;
 91    //    Part1, all the routes in the tree
 92    dfs_tree(0-1);
 93
 94    //    Part2, all the internal routes
 95    for (int i = 0; i < block_cnt; ++i)
 96        generate_block_dist(i);
 97
 98    //    Part3, merge
 99    for (int i = 0; i < n; ++i) 
100        ans += f1[i] * f2[i];
101
102    long long t1 = ans, t2 = n * (n - 1/ 2, d = gcd(t1, t2);
103    cout << t1 / d << "/" << t2 / d << endl;
104}

105
106void dfs_bridge(int u, int fa, int deep) {
107    dfs_color[u] = 1;
108    depth[u] = deep; low[u] = deep;
109
110    for (vector<EdgeNode>::iterator it = g[u].begin(); it != g[u].end(); ++it) {
111        if (it->== fa) continue;
112        if (dfs_color[it->p] == 1{
113            low[u] <?= depth[it->p];
114        }

115        else if (dfs_color[it->p] == 0{
116            dfs_bridge(it->p, u, deep + 1);
117            low[u] <?= low[it->p];
118            if (low[it->p] > depth[u]) {
119                is_bridge[it->id] = true;
120                bridge[bridge_cnt++= it->id;
121            }

122        }

123    }

124
125    dfs_color[u] = 2;
126}

127
128void dfs_tree(int u, int fa) {
129    sum[u] = block[u].size();
130
131    for (vector<EdgeNode>::iterator it = tree[u].begin(); it != tree[u].end(); ++it) {
132        if (it->== fa) continue;
133        dfs_tree(it->p, u);
134        sum[u] += sum[it->p];
135        ans += static_cast<long long>(sum[it->p]) * (n - sum[it->p]) * it->len;
136
137        int eid = it->id;
138        int a = edge[eid][0], b = edge[eid][1];
139        int aa = color[a], bb = color[b];
140        if (aa == u) {
141            f1[a] += sum[it->p]; f1[b] += n - sum[it->p];
142        }

143        else {
144            f1[b] += sum[it->p]; f1[a] += n - sum[it->p];
145        }
    
146    
147
148    }

149}

150
151void generate_block_dist(int idx) {
152    int gg[30][30];
153    fill(gg[0], gg[block[idx].size()], 1000000000);
154
155    for (vector<int>::iterator it = block[idx].begin(); it != block[idx].end(); ++it) {
156        int u = *it;
157        int uu = it - block[idx].begin();
158        for (vector<EdgeNode>::iterator eit = g[u].begin(); eit != g[u].end(); ++eit) {
159            int v = eit->p;
160            if (color[v] != idx) continue;
161            int vv = find(block[idx].begin(), block[idx].end(), v) - block[idx].begin();
162            gg[uu][vv] = eit->len;
163        }

164    }

165
166    int n = block[idx].size();
167    for (int j = 0; j < n; ++j)
168        for (int i = 0; i < n; ++i)
169            for (int k = 0; k < n; ++k)
170                gg[i][k] <?= gg[i][j] + gg[j][k];
171    for (int i = 0; i < n; ++i) {
172        long long &val = f2[block[idx][i]];
173        val = 0;
174        for (int j = 0; j < n; ++j)
175            if (j != i) val += gg[i][j];
176    }

177
178    for (int i = 0; i < n; ++i)
179        for (int j = i + 1; j < n; ++j) {
180            ans += gg[i][j];
181            ans += static_cast<long long>(gg[i][j]) * f1[block[idx][i]] * f1[block[idx][j]];
182        }

183
184}

185
186void dfs_block(int u, int fa, int block_id) {
187    color[u] = block_id; block[block_id].push_back(u);
188    vis[u] = true;
189
190    for (vector<EdgeNode>::iterator it = g[u].begin(); it != g[u].end(); ++it) {
191        if ((!is_bridge[it->id]) && (!vis[it->p])) 
192            dfs_block(it->p, u, block_id);
193    }

194}

195
196long long gcd(long long a, long long b) {
197    return b == 0 ? a : gcd(b, a % b);
198}

199

    
2898       Greedy Grave Robber  
24个宝藏,搜12个,把他们的机关触发情况存入hash or map,然后搜右边12个,查表。
很经典的想法了。
   
2899       Hangzhou Tour     
状态f[st][i][j], st表示已访问的顶点,i表示目前位置,j表示自行车位置,dp。
注意f[st][i][j]只可能转移到>=st的状态。有序性存在。
对相同的st的那些状态使用dijstra or SPFA.

2900       Icecream      
dp, f[i][j][k] = 使用前i个icecream, 组成长度为j, 最后一个元素值为k的方案数。
复杂度2000 * 2000 * 100...10s够了。

2901       MV Maker    Recommended
f[p][a][b] = 长度为2^p + 1, 第一个是a, 最后一个是b的最大value.
然后拼接~,复杂度O(n^3*logL)
CODE
 1//    ZOJ Monthly, January 2008, MV Maker
 2//    Written By FreePeter
 3
 4#include <cstdio>
 5#include <cstring>
 6#include <iostream>
 7
 8using namespace std;
 9
10const int MaxN = 100 + 10;
11const long long INF = 1000000000000000LL;
12long long f[20][MaxN][MaxN], g[2][MaxN];
13
14int main() {
15    int t;
16    cin >> t;
17    for (; t > 0--t) {
18        int n, l;
19        cin >> n >> l;
20        for (int i = 0; i < n; ++i)
21            for (int j = 0; j < n; ++j)
22                cin >> f[0][i][j];
23
24        --l;
25        
26        int lev = 0;
27        for (int i = 0; (1 << (i + 1)) <= l; ++i) {
28            for (int j = 0; j < n; ++j)
29                for (int k = 0; k < n; ++k) {
30                    f[i + 1][j][k] = -INF;
31                    for (int x = 0; x < n; ++x)
32                        f[i + 1][j][k] >?= f[i][j][x] + f[i][x][k];
33                }

34            ++lev;
35        }

36
37        int cur = 0;
38        fill(g[cur], g[cur] + n, 0);
39        for (int i = lev; i >= 0--i) {
40            if (l < (1 << i)) continue;
41            l -= (1 << i);
42            
43            cur = 1 - cur;
44            fill(g[cur], g[cur] + n, -INF);
45            for (int j = 0; j < n; ++j)
46                for (int k = 0; k < n; ++k)
47                    g[cur][k] >?= g[1 - cur][j] + f[i][j][k];
48        }

49        
50        cout << *max_element(g[cur], g[cur] + n) << endl;
51    }

52    return 0;
53}

54

     
2902       Ten drops     
模拟,注意这句
Of cause, a left click in grid without blob should be ignored because it's meaningless.


你可能感兴趣的:(ZOJ Monthly, January 2008解题报告)