题解:P14518 [NFLSPC #8] APLSPC
P14518 [NFLSPC #8] APLSPC
毒瘤题!
我竟然能写黑题题解了!
本题由 @_Mortis_、@LuoXH 和 @xzy_caiji 在机房共同讨论完成,本蒟蒻仅将思路整理后写成题解。
题意
我们需要编写一个程序,要求:
- 不含任何 C++ 和 python 的关键字
- 在 C++ 和 python 语言下都能输出自身(不过滤换行)
思路
2pts
该部分要求程序能在 C++ 运行下输出自身。
正常的程序想要输出自身只会无限套娃,因为输出自己的部分需要再次输出,比如:。
main(){char*s="main(){char*s=...;__builtin_printf(s);}";__builtin_printf(s);}
这时我们只需要将省略号部分改为 %c%s%c,在 __builtin_printf 的参数后添加 34,s,34(34 为引号),相当于省略号部分就是自身。这样我们就利用 printf 的格式化输出解决了这个问题。
:::warning[注意]{open}
代码不能含有关键字 char。
我们需要利用 define 的特性:在 char 中间加上 ## 变成 ch##ar 并不影响编译。如:#define c ch##ar。
:::
最终得到 2pts 代码:
#define c ch##ar
main(){c*s="#define c ch##ar%cmain(){c*s=%c%s%c;__builtin_printf(s,10,34,s,34);}";__builtin_printf(s,10,34,s,34);}
10pts
这部分要求代码在 python 下也能编译通过,还是比较容易的。
注意到 #define 中的 # 在 python 中恰好是注释。
那么我们可以将代码全 define 成 print 这种在 python 中可以编译的函数。
10 pts 代码:
#define c ch##ar
#define print c*s="#define c ch##ar%c#define print c*s=%c%s%c;main(){__builtin_printf(s,10,34,s,34,10);}%cprint";main(){__builtin_printf(s,10,34,s,34,10);}
print
#define c ch##ar
#define print c*s="#define c ch##ar%c#define print c*s=%c%s%c;main(){__builtin_printf(s,10,34,s,34,10);}%cprint";main(){__builtin_printf(s,10,34,s,34,10);}
print
100pts
与 C++ 类似,在 python 中能输出自己的代码长这样(加上 end= 是为了避免换行):
I="I=%c%s%c%cprint(end=I%%(34,I,34,10))"
print(end=I%(34,I,34,10))
我们又发现,在 C++ 中,定义变量时变量类型和变量名之间是可以换行的,如:
char
c;
那么,一个基本思路就出来了:将变量类型 define 成 python 的函数,按上面的方法换行写,就能实现在 C++ 和 python 中同时定义一个字符串;将 C++ 中的主函数 define 成 print,就能实现输出!
一个不知道多少分的代码:
#define id ch##ar*
#define print(a) main(){__builtin_printf(I,10,10,10,34,I,34);}
id
I="#define id ch##ar*%c#define print(a) main(){__builtin_printf(I,10,10,10,34,I,34);}%cid%cI=%c%s%c;print(end=I%%(10,10,10,34,I,34))";print(end=I%(10,10,10,34,I,34))
#define id ch##ar*
#define print(a) main(){__builtin_printf(I,10,10,10,34,I,34);}
id
I="#define id ch##ar*%c#define print(a) main(){__builtin_printf(I,10,10,10,34,I,34);}%cid%cI=%c%s%c;print(end=I%%(10,10,10,34,I,34))";print(end=I%(10,10,10,34,I,34))
253b。
我们发现 print(a) 后的空格可以去掉。这样代码长度来到了 251b,99pts。
最后,@LuoXH 发现 char* 可以用 auto 代替。省下 2b,100pts。
最终代码(燃尽了):
#define id au##to
#define print(a)main(){__builtin_printf(I,10,10,10,34,I,34);}
id
I="#define id au##to%c#define print(a)main(){__builtin_printf(I,10,10,10,34,I,34);}%cid%cI=%c%s%c;print(end=I%%(10,10,10,34,I,34))";print(end=I%(10,10,10,34,I,34))
#define id au##to
#define print(a)main(){__builtin_printf(I,10,10,10,34,I,34);}
id
I="#define id au##to%c#define print(a)main(){__builtin_printf(I,10,10,10,34,I,34);}%cid%cI=%c%s%c;print(end=I%%(10,10,10,34,I,34))";print(end=I%(10,10,10,34,I,34))