• 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

  • 相关阅读:
    DOM官方文档学习总结
    python安装BeautifulSoup库解析HTML页面
    操作datatable数据
    aod.net连接字符串大全
    jqery对于select的操作
    希尔排序算法
    冒泡排序算法
    归并排序(分治法)
    随机函数
    【题解】LibreOJ #6279. 数列分块入门 3
  • 原文地址:https://www.cnblogs.com/LyonLys/p/2012MUTC7_Lyon.html
Copyright © 2020-2023  润新知