Aya Code Golf A~E 本人代码

· · 个人记录

下面公布自己在 Aya Code Golf 中 A~E 题的赛时(和赛后)代码。它们很可能不是最优的。

允许将本文中的代码(优化后)提交至 滴叉 Code Golf,但是要求提交后将修改后的代码发送给我或公布

A

憨憨作者读漏了牌已经排好序的条件。

char s[99],*i;x,d,c,f;main(e){gets(s);while(gets(s)){x=d=e=0;for(c=99;c--&&e<4;)for(e=0,i=s+17;i--!=s;x|=*i==88,d|=*i==68)e+=*i==c;puts(e>3||x&d?"yes":"no");}}

格式化后:

char s[99], *i;
x, d, c, f; // 无类型说明的全局变量默认为 int
main(e){ // main 可以省略 int,参数的 int 也可以省
    gets(s);
    while (gets(s)){
        x = d = e = 0;
        for (c = 99; c-- && e < 4;)
          // 枚举每个字符,如果上个字符出现次数达到 4 就退出
            for (e = 0, i = s + 17; i-- != s; x |= *i == 88, d |= *i == 68)
              // 枚举每张牌,并判断其是不是大小王
                e += *i == c;
        puts(e > 3 || x & d ? "yes" : "no");
    }
}

B

a[1<<21],i=8,j,k,s,l;main(T){while(i--)for(j=10;j--;a[(21<<i*2)+(2<<j*2)]=1);scanf("%d",&T);while(T--){for(l=s=0,i=4;i--;s+=1<<j*2)scanf("%d",&j);for(k=10;k--;)l|=a[s+(1<<k*2)];puts("0\0001"+l*2);}}

格式化后:

a[1 << 21], i = 8, j, k, s, l;
main(T) {
    while (i--)
        for (j = 10; j--; a[(21 << i * 2) + (2 << j * 2)] = 1); // 先求出所有符合题意的五元组,用四进制数记下来
    scanf("%d", &T);
    while (T--) {
        for (l = s = 0, i = 4; i--; s += 1 << j * 2)
            scanf("%d", &j); // 读入
        for (k = 10; k--;)
            l |= a[s + (1 << k * 2)]; // 枚举第五张牌
        puts("0\0001" + l * 2);
          // 画 蛇 添 足,puts(l?"1":"0"); 更短
    }
}

C

long s;main(m){for(scanf("%*d");~scanf("%ld %d",&s,&m);printf(m<2||s&1?"-1\n":"2 %ld %ld\n",s/2,s/2));}

格式化后:

long s;
main(m) {
    for (scanf("%*d"); // * 表示读入后丢弃
      ~scanf("%ld %d", &s, &m); // 返回 -1 代表读不动
      printf(m < 2 || s & 1 ? "-1\n" : "2 %ld %ld\n", s / 2, s / 2)); // 简单构造
}

赛后代码:

long s;main(m){for(scanf("%*d");~scanf("%ld%d",&s,&m);printf(m<2|s&1?"-1\n":"2 %ld %ld\n",s/2,s/2));}

D

M=1e9+7,a[1<<20],i,X=1e9,Y=1;main(n){scanf("%d",&n);for(;i++^n;)scanf("%d",a+i),X=X<a[i]?X:a[i];for(;--i;)Y=a[i]/X*1l*Y%M;printf("%d %d",X,Y);}

格式化后:

// 不是很难看懂
M = 1e9 + 7, a[1 << 20], i, X = 1e9, Y = 1;
main(n) {
    scanf("%d", &n);
    for (; i++ ^ n;)
        scanf("%d", a + i), X = X < a[i] ? X : a[i];
    for (; --i;)
        Y = a[i] / X * 1l * Y % M;
    printf("%d %d", X, Y);
}

E

#include<bits/stdc++.h>
#define W(p) for(int i:d)a+=p abs(H[x]-H[x+i]);
using namespace std;map<long,long>H;unsigned long a,x,y,z;vector d{1,-1,1<<30,-1<<30};main(){cin>>x;while(cin>>x>>y>>z){x=x<<30|y;W(-);H[x]+=z;W();cout<<a<<"\n";}}

格式化后:

#include <bits/stdc++.h>
#define W(p)        \
    for (int i : d) \
        a += p abs(H[x] - H[x + i]); // p 为符号
using namespace std;
map<long, long> H; // 横纵坐标压到一个数
unsigned long a, x, y, z;
vector d{1, -1, 1 << 30, -1 << 30}; // 这样方便枚举相邻格子
main() {
    cin >> x;
    while (cin >> x >> y >> z) {
        x = x << 30 | y;
        W(-);
        H[x] += z;
        W();
        cout << a << "\n";
    }
}

尽管上面的代码有许多肉眼可见的优化之处,但它仍是赛时最短代码。

赛后代码:

#include<bits/stdc++.h>
using namespace std;map<long,long>H;uint64_t a,x,y,W=2e9;main(long z){for(cin>>z;cin>>x>>y>>z;cout<<a<<"\n")for(H[x+=y*W]+=z;int i:{y=1,-y,W,-W})a+=clamp(H[x]-H[x+i],0l,z)*2-z;}

格式化后:

#include <bits/stdc++.h>
using namespace std;
map<long, long> H;
uint64_t a, x, y, W = 2e9; // uint64_t = unsigned long long
main(long z){
    for (cin >> z; cin >> x >> y >> z; cout << a << "\n") // 读入
        for (H[x += y * W] += z; int i : {y = 1, -y, W, -W}) 
          // 循环开始前 x += y * W; H[x] += z
          // 随后枚举四个方向(1 与 W 类型不同,不能直接写 {1, -1, W, -W})
            a += clamp(H[x] - H[x + i], 0l, z) * 2 - z;
            // clamp(a, l, r) = max(min(a, r), l)
}

后记

对代码长度的压缩远不只是删除空白字符、使用单字母变量名那么简单,它需要你了解你使用的语言、适时合并语句、精心调整代码逻辑,有时还要求你掌握一门不可读的语言(对于不限制语言的 code golf)。在此欢迎大家来玩 破防人五号 Code Golf。