• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
LyonLys
愿意在角落唱沙哑的歌 再大声也都是给你 请用心听 不要说话 Contact me via E-mail: lyon.lys@gmail.com
博客园    首页    新随笔    联系   管理    订阅  订阅

2012 MUTC 7 总结

题解链接:http://page.renren.com/601081183/note/865867924

hdu题号:4360~4369

  今天状态不太好。中午,我带着疲惫的身躯去到机房,但是开门的人迟迟没来,对于我们的比赛开始时间也就延迟了几分钟。今天也是很久都没有队伍带榜,不过我一打开题目就看懂了两个,一个是1006,另外的是1001。

  比赛刚开始的时候,我1001还没更新题意,所以没敢试这题,不过初步可以知道是最短路。然后,我观察了一下1006的输入输出,我很快就发现这个对称图形只需统计其中一部份的可操作点的个数,然后快速幂一下,答案就出来了。我第一遍打出来的程序出现了一个问题,就是点的数目居然数多了。于是我又想了一下,画一下图,很快我又发现了,这是要统计1/8的正方形,而不是1/4,。于是我就赶紧改了,测试数据通过以后就立马扔了上去,不过返回了一个TLE。然后,我就很郁闷的想了一下,不能偷懒直接用bool数组来储存点的状态,而是应该用一个点的结构体来储存,在统计前排一下序,然后挑出非重复点,最后用1/8块中的点数来减去点的个数,这样就得到可操作点的个数了。

  代码最快速度只需15ms,差距实在是大啊!

1006(hdu 4365)的代码:

View Code
  1 #include <cstdlib>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 
  7 using namespace std;
  8 typedef __int64 ll;
  9 const int maxn = 5005;
 10 const ll mod = 100000007;
 11 
 12 void scan(int &k)
 13 {
 14     char c;
 15     while ((c = getchar()) && (c > '9' || c < '0'));
 16         k = c - '0';
 17     while((c = getchar()) && (c <= '9' && c >= '0'))
 18         k = k * 10 + c - '0';
 19 }
 20 
 21 struct point
 22 {
 23     int x;
 24     int y;
 25 
 26     bool operator<(const point & a) const
 27     {
 28         if (a.x != x) return x < a.x;
 29         return y < a.y;
 30     }
 31 } p[maxn];
 32 
 33 int cal(int n, int m)
 34 {
 35     int cnt = 0;
 36     int t;
 37 
 38     t = n / 2;
 39     if (n & 1) t++;
 40     if (!m) return t * (t + 1) / 2;
 41     sort(p + 1, p + m + 1);
 42     cnt++;
 43     for (int i = 2; i <= m; i++)
 44     {
 45         if (p[i - 1].x == p[i].x && p[i - 1].y == p[i].y) continue;
 46         cnt++;
 47     }
 48 
 49     /*
 50         if (n & 1){
 51             t = n / 2;
 52             for (int i = 1; i <= t + 1; i++){
 53                 for (int j = i; j <= t + 1; j++){
 54                     if (!mp[i][j]) cnt++;
 55                 }
 56             }
 57         }
 58         else{
 59             t = n / 2;
 60             for (int i = 1; i <= t; i++){
 61                 for (int j = i; j <= t; j++){
 62                     if (!mp[i][j]) cnt++;
 63                 }
 64             }
 65         }
 66      */
 67 #ifndef ONLINE_JUDGE
 68     printf("t  %d\n", t);
 69 #endif
 70     return t * (t + 1) / 2 - cnt;
 71 }
 72 
 73 void con(int n, int &x, int &y)
 74 {
 75     int t = n >> 1;
 76 
 77     if (n & 1)
 78     {
 79         if (x > t) x = n - x + 1;
 80         if (y > t + 1) y = n - y + 1;
 81     } else
 82     {
 83         if (x > t) x = n - x + 1;
 84         if (y > t) y = n - y + 1;
 85     }
 86     if (x > y)
 87     {
 88         t = x;
 89         x = y;
 90         y = t;
 91     }
 92 }
 93 
 94 ll work(ll k, int m)
 95 {
 96     ll ret = 1;
 97 
 98     while (m){
 99         if (m & 1) ret *= k, ret %= mod;
100         k *= k;
101         k %= mod;
102         m >>= 1;
103     }
104 
105     return ret;
106 }
107 
108 bool deal()
109 {
110     int n, m, k;
111     int x, y;
112 
113     if (scanf("%d%d%d", &n, &m, &k) == EOF) return false;
114     /*
115     for (int i = 1, end = (n >> 1) + 1; i <= end; i++){
116         for (int j = 1; j <= end; j++){
117             mp[i][j] = false;
118         }
119     }
120      */
121     for (int i = 1; i <= m; i++)
122     {
123         scan(x);
124         scan(y);
125         x++;
126         y++;
127         con(n, x, y);
128 #ifndef ONLINE_JUDGE
129         printf("con  x %d  y %d\n", x, y);
130 #endif
131         //mp[x][y] = true;
132         p[i].x = x;
133         p[i].y = y;
134     }
135 
136     m = cal((ll)n, m);
137     printf("%I64d\n", work(k, m));
138 
139     return true;
140 }
141 
142 int main()
143 {
144 #ifndef ONLINE_JUDGE
145     freopen("in", "r", stdin);
146 #endif
147     while (deal());
148 
149     return 0;
150 }

 

  我出完这题以后,我的队友已经将1003的转移方程写好了,于是我就立马让位置给他,让他赶紧打上去。dp的题代码 长度通常都不大,所以他很快就打好了。可惜的是,难得让他完成一题,结果这题是要用单调队列优化的,所以结果是TLE。然后我们花了好长时间想优化的方法,可惜还是没想到。赛后,师兄告诉我们用单调队列两边各扫一次,得到两个单调队列,然后,对于递增和递减的区间分别用两种不同的队列更新。据说还可以用二分搜索来加速,思路我已经有了,代码明天再打吧!

  然后我就尝试这做1001,我把输入输出都打好了,就连拆点的操作也想好了,不过当时状态真实相当不好,忘记了spfa的写法,搞到搞半天yy了个dij+heap,最后还要写烂了,最终只好放弃。回来宿舍后,打了一遍,sample轻松通过,不过就是没想到这里可以有自环,还可以有等多个自环原地转啊转的!所以在我查看数据之前都没有意识到这个问题。当然,改过来以后就ac了。

1001(hdu 4360)的代码:

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <queue>
  5 #include <algorithm>
  6 #include <map>
  7 #define ONLINE_JUDGE 1
  8 using namespace std;
  9 
 10 typedef __int64 ll;
 11 
 12 const int maxv = 1500;
 13 const int maxe = 15000;
 14 const ll inf = 1000000000000;
 15 
 16 map<char, int> lt;
 17 struct edge{
 18     int s, t;
 19     ll l;
 20     bool operator < (const edge &x) const{
 21         return s < x.s;
 22     }
 23 }E[maxe << 1];
 24 
 25 ll dis[maxv << 2];
 26 int cnt[maxv << 2], me[maxe << 1];
 27 int q[maxv << 2], qh, qt;
 28 bool inq[maxv << 2];
 29 
 30 void init(){
 31     lt['L'] = 0;
 32     lt['O'] = 1;
 33     lt['V'] = 2;
 34     lt['E'] = 3;
 35 }
 36 
 37 void spfa(int v, int e, int s){
 38     qh = qt = 0;
 39     sort(E, E + e);
 40 
 41     int p = 0;
 42 
 43     for (int i = 0; i < v; i++){
 44         inq[i] = false;
 45         dis[i] = inf;
 46         cnt[i] = 0;
 47     }
 48     for (int i = 0; i < e; i++){
 49         while (p <= E[i].s) me[p++] = i;
 50     }
 51     while (p <= v) me[p++] = e;
 52 #ifndef ONLINE_JUDGE
 53     for (int i = 0; i < 20; i++){
 54         printf("me %d : %d    E : %d %d %I64d    dis %I64d\n", i, me[i], E[i].s, E[i].t, E[i].l, dis[i]);
 55     }
 56 #endif
 57 
 58     for (int i = me[s]; i < me[s + 1]; i++){
 59         int et = E[i].t;
 60 
 61         if (dis[et] > E[i].l) dis[et] = E[i].l;
 62         cnt[et] = 1;
 63         if (!inq[et]){
 64             q[qt++] = et;
 65             inq[et] = true;
 66         }
 67     }
 68     while (qh < qt){
 69         int cur = q[qh++];
 70 #ifndef ONLINE_JUDGE
 71         printf("pass %d\n", cur);
 72 #endif
 73 
 74         inq[cur] = false;
 75          for (int i = me[cur]; i < me[cur + 1]; i++){
 76             int et = E[i].t;
 77 
 78             if (dis[et] > dis[cur] + E[i].l){
 79                 dis[et] = dis[cur] + E[i].l;
 80                 cnt[et] = cnt[cur] + 1;
 81                 if (!inq[et]){
 82                     q[qt++] = et;
 83                     inq[et] = true;
 84                 }
 85             }
 86             else if (dis[et] == dis[cur] + E[i].l && cnt[et] < cnt[cur] + 1){
 87                 cnt[et] = cnt[cur] + 1;
 88                 if (!inq[et]){
 89                     q[qt++] = et;
 90                     inq[et] = true;
 91                 }
 92             }
 93         }
 94     }
 95 }
 96 
 97 
 98 void deal(int cc){
 99     int n, m, N;
100 
101     scanf("%d%d", &n, &m);
102     N = n << 2;
103     for (int i = 0; i < m; i++){
104         int s, t, len, kd;
105         char buf[3];
106 
107         scanf("%d%d%d%s", &s, &t, &len, buf);
108         s--; t--;
109         kd = lt[buf[0]];
110         E[i << 1].s = kd * n + s;
111         E[i << 1].t = ((kd + 1) % 4) * n + t;
112         E[i << 1].l = len;
113         E[i << 1 | 1].s = kd * n + t;
114         E[i << 1 | 1].t = ((kd + 1) % 4) * n + s;
115         E[i << 1 | 1].l = len;
116     }
117 
118     m <<= 1;
119     spfa(N, m, 0);
120 
121     if (dis[n - 1] < inf) printf("Case %d: Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n", cc, dis[n - 1], cnt[n - 1] / 4);
122     else printf("Case %d: Binbin you disappoint Sangsang again, damn it!\n", cc);
123 }
124 
125 int main(){
126     int T;
127 
128 #ifndef ONLINE_JUDGE
129     freopen("in", "r", stdin);
130     freopen("out", "w", stdout);
131 #endif
132     init();
133     scanf("%d", &T);
134     for (int i = 1; i <= T; i++){
135         deal(i);
136     }
137 
138     return 0;
139 }

 

  最后半个钟,我的队友才辛苦看懂1005这原本很水的模拟题。然后就手忙脚乱的打上代码,提交了上去。思路是对的,sample也是对的,不过我一开始的时候没有处理行末的空格和最后的空行,所以直到比赛结束我们都没有通过这题。赛后改了这个问题以后就立马过了.......T^T    这下玩大了,那时还以为没改会先得到PE,结果oj实在是狠,直接返回wa,搞到我们先是觉得是想法错误了,所以更改的方向也错了......

1005(hdu 4364)的代码:

View Code
 1 #include <cstdio>
 2 
 3 int mt[4][4];
 4 int op[4][4] = {2, 3, 1, 1, 1, 2, 3, 1, 1, 1, 2, 3, 3, 1, 1, 2};
 5 
 6 int deal(int OP, int in){
 7     switch(OP){
 8         case 1: return in;
 9         case 2: {
10             in <<= 1;
11             if (in > 0xff){
12                 in ^= 0x1b;
13             }
14             return in;
15         }
16         case 3:{
17             int tmp = in << 1;
18             in = tmp ^ in;
19             if (in > 0xff){
20                 in ^= 0x1b;
21             }
22             return in;
23         }
24     }
25     return 0;
26 }
27 
28 int main(){
29     int T;
30 #ifndef ONLINE_JUDGE
31     freopen("in", "r", stdin);
32 #endif
33     scanf("%d", &T);
34     while (T--){
35         for (int i = 0; i < 4; i++){
36             for (int j = 0; j < 4; j++){
37                 scanf("%X", &mt[i][j]);
38 #ifndef ONLINE_JUDGE
39                 printf("%d ", mt[i][j]);
40 #endif
41             }
42 #ifndef ONLINE_JUDGE
43             puts("");
44 #endif
45         }
46         int out;
47 
48         for (int i = 0; i < 4; i++){
49             for (int j = 0; j < 4; j++){
50                 out = 0;
51                 for (int k = 0; k < 4; k++){
52                     out ^= deal(op[i][k], mt[k][j]);
53                 }
54                 if (j < 3) printf("%02X ", out & 0xff);
55                 else printf("%02X\n", out & 0xff);
56             }
57         }
58 
59         if (T) puts("");
60     }
61 
62     return 0;
63 }

 

  吸取教训了,以后不能靠oj来判断是否格式错误,而是要根据题意来判断!

  继续努力!

——written by Lyon

 

http://acm.hdu.edu.cn/showproblem.php?pid=4365

posted @ 2012-08-15 00:28  LyonLys  阅读(300)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3