论在键盘的大部分标点符号都坏掉的情况下都可以做些什么
chengyifan91 · · 休闲·娱乐
(本人平时并不擅长 C++,很多内容和真实语法有偏差,还请见谅。另外,本文中的符号指不能在 C++ 语言中作为变量名的可见字符。作为注释的 / 不被算作使用符号。)
起因
受到机房大佬的文章启发,我就在想既然排序都能用 %:<>() 这
- 归并排序求逆序对。
- 动态开点权值线段树。
- 树状数组+离散化。
被淘汰的算法
归并排序需要用到递归,然而只用 %:<>() 想要实现递归是及其困难的,于是归并排序和线段树就遗憾离场了。
一些小技巧
要写树状数组,加减法,那么如何实现且保证复杂度呢?
替代运算符
在 C++ 中,有一种东西叫做替代运算符,下面是一些会用到的替代运算符:
| 运算符 | 替代运算符 |
|---|---|
& |
bitand |
\| |
bitor |
^ |
xor |
~ |
compl |
&= |
and_eq |
\|= |
or_eq |
^= |
xor_eq |
\|\| |
or |
! |
not |
比较搞笑的是,bitand 还可以作为引用变量使用。
还有一些字符不是运算符,但是也可以被两个字符替代,这是早期 C++ 为了防止大家的键盘上没有一些字符而提供的。
| 原字符 | 替代字符 |
|---|---|
# |
%: |
{ |
<% |
} |
%> |
[ |
<: |
] |
:> |
我们发现这些替代字符恰好都在允许使用的字符的范围内!
不过有很多运算符都是没有替代运算符的,但是我们可以自己实现,比如 a = b 就是 a xor_eq b xor a,a == b 就是 not (a xor b),a <= b 就是 a < b or not (a xor b),等等。
加法
我们已经知道了替代运算符,那怎么用这些运算符完成加减法呢?首先,给出一种
我们发现在加法和异或的本质区别就是加法存在进位,因此我们可以将两个数的和转为异或和以及进位两个部分,即
:::info[复杂度证明]
假设
进行一步转化后
我们发现
while (a bitand b) <%
if (a xor_eq b) <%%>
if (b and_eq a xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (a or_eq b) <%%>
在 C++ 中,
回到正题
接下来,我们就可以开始实现逆序对了!
需要用到的头文件:iostream,ranges,vector,algorithm,建议使用 C++ 20。
离散化
离散化同样有很多种实现,比如 lower_bound、map 和直接 sort 等等。这里我使用了手写 lower_bound 的方法。
先声明一些变量,由于有符号的限制,我们可以用 for (auto name : {x}) 来声明一个变量,也就是遍历一个只有一个元素的初始化列表。
for (int n : <%0%>)
for (long long ans : <%0%>) <%
if (std::cin >> n) <%%>
for (auto a : <%std::vector<int>(n)%>)
for (auto b : <%std::vector<int>(n)%>)
for (auto tr : <%std::vector<int>(n<<1)%>) <%
其中 tr 的下标从 1 开始,因此需要开到比 << 可以用,所以就开到了 n<<1。
接下来就是真正的离散化部分了。
for (int i : std::views::iota(0) bitor std::views::take(n)) <%
for (int l : <%0%>) for (int r : <%n%>) for (int res : <%0%>) <% // res 是二分结果
for (int b : <%static_cast<int>(0xffffffffU)%>) <% // static_cast<int>(0xffffffffU) 是 -1,这段代码相当于 r--
while (r bitand b) <%
if (r xor_eq b) <%%>
if (b and_eq r xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (r or_eq b) <%%>
%>
while (l < r or not (l xor r)) <% // l <= r,闭区间二分
for (int mid : <%l%>) <%
// 这一部分相当于 mid = (l + r) >> 1
for (int b : <%r%>) <%
while (mid bitand b) <%
if (mid xor_eq b) <%%>
if (b and_eq mid xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (mid or_eq b) <%%>
%>
if (mid xor_eq mid xor (mid >> 1)) <%%>
// 二分判断,b[mid] >= a[i]
if (b<:mid:> > a<:i:> or not (b<:mid:> xor a<:i:>)) <%
if (res xor_eq res xor mid) <%%> // res = mid
if (r xor_eq r xor mid) <%%> // r = mid
for (int b : <%static_cast<int>(0xffffffffU)%>) <% // r--
while (r bitand b) <%
if (r xor_eq b) <%%>
if (b and_eq r xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (r or_eq b) <%%>
%>
%> else <%
if (l xor_eq l xor mid) <%%> // l = mid
for (int b : <%1%>) <% // l++
while (l bitand b) <%
if (l xor_eq b) <%%>
if (b and_eq l xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (l or_eq b) <%%>
%>
%>
%>
%>
if (a<:i:> xor_eq a<:i:> xor res) <%%> // a[i] = res
%>
%>
树状数组
然后就是激动人心的树状数组部分了。树状数组的核心就是 lowbit,但是我们发现 lowbit(x) 显然硬求比 x & (-x) 更好写,常数更小,于是就可以这样实现:
for (auto l : <%1%>) <%
while (not (x bitand 1)) <%
if (l xor_eq l xor (l << 1)) {}
if (x xor_eq x xor (x >> 1)) {}
%>
%>
当然实际实现会有些不一样。
先声明变量
for (int i : std::views::iota(0) bitor std::views::take(n)) <%
for (int x : <%a<:i:>%>) <%
然后由于树状数组的下标从
for (int b : <%1%>) <%
while (x bitand b) <%
if (x xor_eq b) <%%>
if (b and_eq x xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (x or_eq b) <%%>
%>
正常的树状数组求
for (long long b : <%i%>) <%
while (ans bitand b) <%
if (ans xor_eq b) <%%>
if (b and_eq ans xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (ans or_eq b) <%%>
%>
然后是查询
for (int t : <%x%>) for (int l : <%0%>) <% // l 用于求 lowbit
while (t) <%
for (long long b : <%tr<:t:>%>) <% // ans += ~tr[t]
if (b xor_eq b xor compl b) <%%>
while (ans bitand b) <%
if (ans xor_eq b) <%%>
if (b and_eq ans xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (ans or_eq b) <%%>
%>
for (long long b : <%1%>) <% // ans++,ans += ~tr[t]+1 相当于 ans -= tr[t]
while (ans bitand b) <%
if (ans xor_eq b) <%%>
if (b and_eq ans xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (ans or_eq b) <%%>
%>
if (l xor_eq l xor 1) <%%> // l = 1
for (int tmp : <%t%>) <% // 求 l
while (not (tmp bitand 1)) <%
if (l xor_eq l xor (l << 1)) <%%>
if (tmp xor_eq tmp xor (tmp >> 1)) <%%>
%>
%>
if (t xor_eq l) <%%>
%>
%>
最后是单点修改。
for (int t : <%x%>) for (int l : <%0%>) <%
while (t < n or not (t xor n)) <% // t <= n
for (int b : <%1%>) <% // tr[t]++
while (tr<:t:> bitand b) <%
if (tr<:t:> xor_eq b) <%%>
if (b and_eq tr<:t:> xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (tr<:t:> or_eq b) <%%>
%>
if (l xor_eq l xor 1) <%%> // l = 1
for (int tmp : <%t%>) <% // 求 lowbit
while (not (tmp bitand 1)) <%
if (l xor_eq l xor (l << 1)) <%%>
if (tmp xor_eq tmp xor (tmp >> 1)) <%%>
%>
%>
while (t bitand l) <% // t += l
if (t xor_eq l) <%%>
if (l and_eq t xor l) <%%>
if (l xor_eq l xor (l << 1)) <%%>
%>
if (t or_eq l) <%%>
%>
%>
完整代码
%:include<iostream>
%:include<ranges>
%:include<vector>
%:include<algorithm>
int main() <%
if (std::ios::sync_with_stdio(0)) <%%>
for (int n : <%0%>) for (long long ans : <%0%>) <%
if (std::cin >> n) <%%>
for (auto a : <%std::vector<int>(n)%>) for (auto b : <%std::vector<int>(n)%>) for (auto tr : <%std::vector<int>(n<<1)%>) <%
for (auto bitand i : a) if (std::cin >> i) <%%>
for (int i : std::views::iota(0) bitor std::views::take(n)) if (b<:i:> xor_eq a<:i:>) <%%>
for (auto i : <%std::ranges::sort(b)%>) <%%>
for (int i : std::views::iota(0) bitor std::views::take(n)) <%
for (int l : <%0%>) for (int r : <%n%>) for (int res : <%0%>) <%
for (int b : <%static_cast<int>(0xffffffffU)%>) <%
while (r bitand b) <%
if (r xor_eq b) <%%>
if (b and_eq r xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (r or_eq b) <%%>
%>
while (l < r or not (l xor r)) <%
for (int mid : <%l%>) <%
for (int b : <%r%>) <%
while (mid bitand b) <%
if (mid xor_eq b) <%%>
if (b and_eq mid xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (mid or_eq b) <%%>
%>
if (mid xor_eq mid xor (mid >> 1)) <%%>
if (b<:mid:> > a<:i:> or not (b<:mid:> xor a<:i:>)) <%
if (res xor_eq res xor mid) <%%>
if (r xor_eq r xor mid) <%%>
for (int b : <%static_cast<int>(0xffffffffU)%>) <%
while (r bitand b) <%
if (r xor_eq b) <%%>
if (b and_eq r xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (r or_eq b) <%%>
%>
%> else <%
if (l xor_eq l xor mid) <%%>
for (int b : <%1%>) <%
while (l bitand b) <%
if (l xor_eq b) <%%>
if (b and_eq l xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (l or_eq b) <%%>
%>
%>
%>
%>
if (a<:i:> xor_eq a<:i:> xor res) <%%>
%>
%>
for (int i : std::views::iota(0) bitor std::views::take(n)) <%
for (int x : <%a<:i:>%>) <%
for (int b : <%1%>) <%
while (x bitand b) <%
if (x xor_eq b) <%%>
if (b and_eq x xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (x or_eq b) <%%>
%>
for (long long b : <%i%>) <%
while (ans bitand b) <%
if (ans xor_eq b) <%%>
if (b and_eq ans xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (ans or_eq b) <%%>
%>
for (int t : <%x%>) for (int l : <%0%>) <%
while (t) <%
for (long long b : <%tr<:t:>%>) <%
if (b xor_eq b xor compl b) <%%>
while (ans bitand b) <%
if (ans xor_eq b) <%%>
if (b and_eq ans xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (ans or_eq b) <%%>
%>
for (long long b : <%1%>) <%
while (ans bitand b) <%
if (ans xor_eq b) <%%>
if (b and_eq ans xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (ans or_eq b) <%%>
%>
if (l xor_eq l xor 1) <%%>
for (int tmp : <%t%>) <%
while (not (tmp bitand 1)) <%
if (l xor_eq l xor (l << 1)) <%%>
if (tmp xor_eq tmp xor (tmp >> 1)) <%%>
%>
%>
if (t xor_eq l) <%%>
%>
%>
for (int t : <%x%>) for (int l : <%0%>) <%
while (t < n or not (t xor n)) <%
for (int b : <%1%>) <%
while (tr<:t:> bitand b) <%
if (tr<:t:> xor_eq b) <%%>
if (b and_eq tr<:t:> xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (tr<:t:> or_eq b) <%%>
%>
if (l xor_eq l xor 1) <%%>
for (int tmp : <%t%>) <%
while (not (tmp bitand 1)) <%
if (l xor_eq l xor (l << 1)) <%%>
if (tmp xor_eq tmp xor (tmp >> 1)) <%%>
%>
%>
while (t bitand l) <%
if (t xor_eq l) <%%>
if (l and_eq t xor l) <%%>
if (l xor_eq l xor (l << 1)) <%%>
%>
if (t or_eq l) <%%>
%>
%>
%>
%>
if (std::cout << ans) <%%>
%>
%>
%>
提交记录:点这里。
更多的思考
除了刚才那三个算法,难道就没有可以用的算法了吗?当然有!我们可以使用分块!虽然
由于没有满分,就不放提交记录了,只给出完整代码,感兴趣的读者可以尝试优化到满分(虽然不太可能)。
%:include<iostream>
%:include<algorithm>
%:include<ranges>
%:include<cmath>
%:include<vector>
int main() <%
if (std::ios::sync_with_stdio(0)) <%%>
for (int n : <%0%>) if (std::cin >> n)
for (int B : <%std::sqrt(n)%>)
for (long long ans : <%0%>)
for (auto a : std::array<%std::vector<int>(n)%>)
for (auto b : <%std::vector<int>(n)%>)
for (auto sum : <%std::vector<int>(n)%>)
for (auto mp : <%std::vector<int>(n)%>)
for (auto pos : <%std::vector<int>(n)%>)
for (auto l : <%std::vector<int>(n)%>)
for (auto r : <%std::vector<int>(n)%>) <%
for (auto bitand i : a) if (std::cin >> i) <%%>
for (int i : std::views::iota(0) bitor std::views::take(n)) if (b<:i:> xor_eq a<:i:>) <%%>
for (auto i : <%std::ranges::sort(b)%>) <%%>
for (int i : std::views::iota(0) bitor std::views::take(n)) <%
for (int l : <%0%>)
for (int r : <%n%>)
for (int res : <%0%>) <%
for (int b : <%0xffffffff%>) <% while (r bitand b) <% if (r xor_eq b) <%%> if (b and_eq r xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (r or_eq b) <%%> %>
while (l < r or not (l xor r)) <%
for (int mid : <%l%>) <%
for (int b : <%r%>) <% while (mid bitand b) <% if (mid xor_eq b) <%%> if (b and_eq mid xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (mid or_eq b) <%%> %>
if (mid xor_eq mid xor (mid >> 1)) <%%>
if (b<:mid:> > a<:i:> or not (b<:mid:> xor a<:i:>)) <%
if (r xor_eq r xor mid) <%%>
for (int b : <%0xffffffff%>) <% while (r bitand b) <% if (r xor_eq b) <%%> if (b and_eq r xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (r or_eq b) <%%> %>
if (res xor_eq res xor mid) <%%>
%> else <%
if (l xor_eq l xor mid) <%%>
for (int b : <%1%>) <% while (l bitand b) <% if (l xor_eq b) <%%> if (b and_eq l xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (l or_eq b) <%%> %>
%>
%>
%>
if (a<:i:> xor_eq a<:i:> xor res) <%%>
%>
%>
for (int i : <%0%>)
for (int t : <%0%>) <%
while (i < n) <%
for (int b : <%1%>) <% while (t bitand b) <% if (t xor_eq b) <%%> if (b and_eq t xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (t or_eq b) <%%> %>if (l<:t:> xor_eq i) <%%>
for (int j : <%i%>) <%
for (int b : <%B%>) <% while (i bitand b) <% if (i xor_eq b) <%%> if (b and_eq i xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (i or_eq b) <%%> %>
while (j < i and j < n) <%
if (pos<:j:> xor_eq t) <%%>
if (r<:t:> xor_eq r<:t:> xor j) <%%>
for (int b : <%1%>) <% while (j bitand b) <% if (j xor_eq b) <%%> if (b and_eq j xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (j or_eq b) <%%> %>
%>
%>
%>
%>
for (int i : std::views::iota(0) bitor std::views::take(n)) <%
for (long long b : <%i%>) <% while (ans bitand b) <% if (ans xor_eq b) <%%> if (b and_eq ans xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (ans or_eq b) <%%> %>
if (pos<:a<:i:>:> xor 1) <%
for (int j : <%0%>) while (j < r<:1:> or not (j xor r<:1:>)) <%
for (long long b : <%mp<:j:>%>) <% if (b xor_eq b xor compl b) <%%> while (ans bitand b) <% if (ans xor_eq b) <%%> if (b and_eq ans xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (ans or_eq b) <%%> %>
for (int b : <%1%>) <% while (j bitand b) <% if (j xor_eq b) <%%> if (b and_eq j xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (j or_eq b) <%%> %>
for (long long b : <%1%>) <% while (ans bitand b) <% if (ans xor_eq b) <%%> if (b and_eq ans xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (ans or_eq b) <%%> %>
%>
for (int j : <%2%>) while (j < pos<:a<:i:>:>) <%
for (long long b : <%sum<:j:>%>) <% if (b xor_eq b xor compl b) <%%> while (ans bitand b) <% if (ans xor_eq b) <%%> if (b and_eq ans xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (ans or_eq b) <%%> %>
for (int b : <%1%>) <% while (j bitand b) <% if (j xor_eq b) <%%> if (b and_eq j xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (j or_eq b) <%%> %>
for (long long b : <%1%>) <% while (ans bitand b) <% if (ans xor_eq b) <%%> if (b and_eq ans xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (ans or_eq b) <%%> %>
%>
for (int j : <%l<:pos<:a<:i:>:>:>%>) while (j < a<:i:> or not (j xor a<:i:>)) <%
for (long long b : <%mp<:j:>%>) <% if (b xor_eq b xor compl b) <%%> while (ans bitand b) <% if (ans xor_eq b) <%%> if (b and_eq ans xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (ans or_eq b) <%%> %>
for (int b : <%1%>) <% while (j bitand b) <% if (j xor_eq b) <%%> if (b and_eq j xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (j or_eq b) <%%> %>
for (long long b : <%1%>) <% while (ans bitand b) <% if (ans xor_eq b) <%%> if (b and_eq ans xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (ans or_eq b) <%%> %>
%>
%> else <%
for (int j : <%0%>) while (j < a<:i:> or not (j xor a<:i:>)) <%
for (long long b : <%mp<:j:>%>) <% if (b xor_eq b xor compl b) <%%> while (ans bitand b) <% if (ans xor_eq b) <%%> if (b and_eq ans xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (ans or_eq b) <%%> %>
for (int b : <%1%>) <% while (j bitand b) <% if (j xor_eq b) <%%> if (b and_eq j xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (j or_eq b) <%%> %>
for (long long b : <%1%>) <% while (ans bitand b) <% if (ans xor_eq b) <%%> if (b and_eq ans xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (ans or_eq b) <%%> %>
%>
%>
for (int b : <%1%>) <% while (mp<:a<:i:>:> bitand b) <% if (mp<:a<:i:>:> xor_eq b) <%%> if (b and_eq mp<:a<:i:>:> xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (mp<:a<:i:>:> or_eq b) <%%> %>
for (int b : <%1%>) <% while (sum<:pos<:a<:i:>:>:> bitand b) <% if (sum<:pos<:a<:i:>:>:> xor_eq b) <%%> if (b and_eq sum<:pos<:a<:i:>:>:> xor b) <%%> if (b xor_eq b xor (b << 1)) <%%> %> if (sum<:pos<:a<:i:>:>:> or_eq b) <%%> %>
%>
if (std::cout << ans) <%%>
%>
%>
更加困难的挑战
相信大家一定听说过一种超级考验码力、耐心和调试能力的题型,没错,就是大模拟!这里我选用了一个比较有代表性的题目:P2586 [ZJOI2008] 杀蚂蚁。
题目坑点
这里说的是常规的代码需要注意的地方。
- 题目没说
n 和m 的含义可能是我眼瞎没看见,我们猜测n 是行,m 是列,发现猜对了(根据样例),我们继续猜测东方向是让列+1 ,又猜对了。 -
如果此时仍有多种选择,蚂蚁先面向正东,如果正东不是可选择的某个方向,它会顺时针转
90^\degree ,再次判断,如果还不是,再顺时针旋转90^\degree ,直到找到可以去的方向。注意这里的“可选择的方向”不是指可达点,而是可达点中信息素最大的。
可能是我语文太差了这个破地方调了半天 -
激光塔有个比较奇怪的特性:它在选定了打击目标后,只要目标在其射程内,塔到目标蚂蚁圆心的连线上的所有蚂蚁(这里“被打到”的判定变成了表示激光的线段与表示蚂蚁的圆有公共点)都会被打到并损
d 格血,但激光不会穿透它的打击目标打到后面的蚂蚁。没错,我又看错成和圆心有公共点了,直接用
\gcd 打蚂蚁了,后面调了半天发现还要用一点数学知识判断圆心和直线的距离。
优化运算
在逆序对中,我们成功写出了
首先,我们需要处理一个 nxt 数组和一个 pre 数组,
这是好处理的,我们只需要让
血量的变化需要
接下来,实现加减法,我们设
-
zh_{i,j}=zh_{i,j-1}+1 -
cj_{i,j}=\begin{cases}cj_{i,j-1}+1&i<j\\cj_{i,j-1}-1&i\ge j\end{cases}
注意一下边界条件即可。
最后是乘法
注意二维数组很难实现,于是我们将编号压成一维数组,用 zh[(i<<8)|j] 和 cj[(i<<8)|j] 代替刚刚的 zh[i][j] 和 cj[i][j],用 mul[(i<<7)|j] 代替刚刚的 mul[i][j]。
代码:
for (int lst : <%0%>) <%
if (pre<:0:> xor_eq compl 0) <%%>
for (int i : std::views::iota(1) bitor std::views::take(1000000)) <%
if (pre<:i:> xor_eq lst) <%%>
if (nxt<:lst:> xor_eq i) <%%>
if (lst xor_eq lst xor i) <%%>
%>
%>
for (int i : std::views::iota(1) bitor std::views::take(200)) <%
if (zh<:i:> xor_eq i) <%%>
if (cj<:i:> xor_eq i) <%%>
%>
for (int i : std::views::iota(1) bitor std::views::take(200)) <%
if (zh<:i<<8:> xor_eq i) <%%>
if (cj<:i<<8:> xor_eq i) <%%>
for (int lst : <%0%>) for (int j : std::views::iota(1) bitor std::views::take(200)) <%
if (zh<:(i<<8) bitor j:> xor_eq nxt<:zh<:(i<<8) bitor lst:>:>) <%%>
if (i < j) <%
if (cj<:(i<<8) bitor j:> xor_eq nxt<:cj<:(i<<8) bitor lst:>:>) <%%>
%> else <%
if (cj<:(i<<8) bitor j:> xor_eq pre<:cj<:(i<<8) bitor lst:>:>) <%%>
%>
if (lst xor_eq lst xor j) <%%>
%>
%>
for (int i : std::views::iota(1) bitor std::views::take(100)) <%
for (int lst : <%0%>) for (int j : std::views::iota(1) bitor std::views::take(100)) <%
if (mul<:(i<<7) bitor j:> xor_eq mul<:(i<<7) bitor lst:>) <%%>
for (int b : <%i%>) <%
while (mul<:(i<<7) bitor j:> bitand b) <%
if (mul<:(i<<7) bitor j:> xor_eq b) <%%>
if (b and_eq mul<:(i<<7) bitor j:> xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (mul<:(i<<7) bitor j:> or_eq b) <%%>
%>
if (lst xor_eq lst xor j) <%%>
%>
if (pw<:i:> xor_eq mul<:(i<<7) bitor i:>) <%%>
%>
代码逻辑
由于给大模拟写题解是困难的事,因此我就说说每个东西都维护什么,其它东西就看你和它有没有缘分了~
// 导入一堆头文件
%:include<iostream>
%:include<vector>
%:include<ranges>
%:include<algorithm>
%:include<climits>
// %:x 相当于 "x",只不过为了省掉 ",只能这么写
%:define str(x) %:x
%:define N 200010
int main() <%
for (int n : <%0%>)
for (int m : <%0%>)
for (int s : <%0%>)
for (int d : <%0%>)
for (int r : <%0%>)
for (int ed : <%0%>) // 蚂蚁是否胜利
for (int mysl : <%0%>) // 活着的蚂蚁数量
for (bool ndg : <%0%>) // 蛋糕有没有被拿
for (int sj : <%0%>) // 当前时间
for (int t : <%0%>)
for (int cnt : <%0%>) // 累计出生的蚂蚁数量 % 6
for (int tot : <%0%>) // 当前蚂蚁的等级
for (auto dj : <%std::vector<int>(N)%>) // 等级
for (auto nl : <%std::vector<int>(N)%>) // 年龄
for (auto ml : <%std::vector<int>(N)%>) // 活动时间 % 5
for (auto xl : <%std::vector<int>(N)%>) // 血量
for (auto zdxl : <%std::vector<int>(N)%>) // 最大血量,可以证明在 int 范围内
for (auto x : <%std::vector<int>(N)%>)
for (auto y : <%std::vector<int>(N)%>)
for (auto px : <%std::vector<int>(N)%>) // 炮塔坐标
for (auto py : <%std::vector<int>(N)%>)
for (auto lx : <%std::vector<int>(N)%>) // 上一秒的蚂蚁坐标
for (auto ly : <%std::vector<int>(N)%>)
for (auto mp : <%std::vector<int>(300)%>) // 二维数组压成一维,mp[(i<<4)|j] 表示 (i,j) 上的蚂蚁编号,如果没有就是 0
for (auto pt : <%std::vector<int>(300)%>) // 同上,这个是是否有炮塔
for (auto xxs : <%std::vector<int>(300)%>) // 同上,这个是信息素
for (auto dg : <%std::vector<int>(N)%>) // 是否有蛋糕
for (auto dx : <%std::vector<int>(4)%>) // 东南西北偏移量
for (auto dy : <%std::vector<int>(4)%>)
for (auto nxt : <%std::vector<int>(1000005)%>) // nxt[i] = i+1
for (auto pre : <%std::vector<int>(1000005)%>) // pre[i] = i-1
for (auto mul : <%std::vector<int>(N)%>)
for (auto zh : <%std::vector<int>(N)%>)
for (auto cj : <%std::vector<int>(N)%>)
for (auto pw : <%std::vector<int>(N)%>)
for (auto jd : <%std::vector<int>(50010005)%>)
for (auto z : <%std::vector<int>(205)%>) <% // 代表等级为 i 的最大血量
接下来就是完整代码啦~
// 导入一堆头文件
%:include<iostream>
%:include<vector>
%:include<ranges>
%:include<algorithm>
%:include<climits>
// %:x 相当于 "x",只不过为了省掉 ",只能这么写
%:define str(x) %:x
%:define N 200010
int main() <%
for (int n : <%0%>)
for (int m : <%0%>)
for (int s : <%0%>)
for (int d : <%0%>)
for (int r : <%0%>)
for (int ed : <%0%>) // 蚂蚁是否胜利
for (int mysl : <%0%>) // 活着的蚂蚁数量
for (bool ndg : <%0%>) // 蛋糕有没有被拿
for (int sj : <%0%>) // 当前时间
for (int t : <%0%>)
for (int cnt : <%0%>) // 累计出生的蚂蚁数量 % 6
for (int tot : <%0%>) // 当前蚂蚁的等级
for (auto dj : <%std::vector<int>(N)%>) // 等级
for (auto nl : <%std::vector<int>(N)%>) // 年龄
for (auto ml : <%std::vector<int>(N)%>) // 活动时间 % 5
for (auto xl : <%std::vector<int>(N)%>) // 血量
for (auto zdxl : <%std::vector<int>(N)%>) // 最大血量,可以证明在 int 范围内
for (auto x : <%std::vector<int>(N)%>)
for (auto y : <%std::vector<int>(N)%>)
for (auto px : <%std::vector<int>(N)%>) // 炮塔坐标
for (auto py : <%std::vector<int>(N)%>)
for (auto lx : <%std::vector<int>(N)%>) // 上一秒的蚂蚁坐标
for (auto ly : <%std::vector<int>(N)%>)
for (auto mp : <%std::vector<int>(300)%>) // 二维数组压成一维,mp[(i<<4)|j] 表示 (i,j) 上的蚂蚁编号,如果没有就是 0
for (auto pt : <%std::vector<int>(300)%>) // 同上,这个是是否有炮塔
for (auto xxs : <%std::vector<int>(300)%>) // 同上,这个是信息素
for (auto dg : <%std::vector<int>(N)%>) // 是否有蛋糕
for (auto dx : <%std::vector<int>(4)%>) // 东南西北偏移量
for (auto dy : <%std::vector<int>(4)%>)
for (auto nxt : <%std::vector<int>(1000005)%>) // nxt[i] = i+1
for (auto pre : <%std::vector<int>(1000005)%>) // pre[i] = i-1
for (auto mul : <%std::vector<int>(N)%>) // mul[(i<<7)|j] = i*j
for (auto zh : <%std::vector<int>(N)%>) // zh[(i<<8)|j] = i+j
for (auto cj : <%std::vector<int>(N)%>) // 同上,这个是 abs(i-j)
for (auto pw : <%std::vector<int>(N)%>) // pw[i] = i*i
for (auto jd : <%std::vector<int>(50010005)%>) // jd[i] = i-d
for (auto z : <%std::vector<int>(205)%>) <% // 代表等级为 i 的最大血量
// 数组的初始化
for (int lst : <%0%>) <%
if (pre<:0:> xor_eq compl 0) <%%>
for (int i : std::views::iota(1) bitor std::views::take(1000000)) <%
if (pre<:i:> xor_eq lst) <%%>
if (nxt<:lst:> xor_eq i) <%%>
if (lst xor_eq lst xor i) <%%>
%>
%>
for (int i : std::views::iota(1) bitor std::views::take(200)) <%
if (zh<:i:> xor_eq i) <%%>
if (cj<:i:> xor_eq i) <%%>
%>
for (int i : std::views::iota(1) bitor std::views::take(200)) <%
if (zh<:i<<8:> xor_eq i) <%%>
if (cj<:i<<8:> xor_eq i) <%%>
for (int lst : <%0%>) for (int j : std::views::iota(1) bitor std::views::take(200)) <%
if (zh<:(i<<8) bitor j:> xor_eq nxt<:zh<:(i<<8) bitor lst:>:>) <%%>
if (i < j) <%
if (cj<:(i<<8) bitor j:> xor_eq nxt<:cj<:(i<<8) bitor lst:>:>) <%%>
%> else <%
if (cj<:(i<<8) bitor j:> xor_eq pre<:cj<:(i<<8) bitor lst:>:>) <%%>
%>
if (lst xor_eq lst xor j) <%%>
%>
%>
for (int i : std::views::iota(1) bitor std::views::take(100)) <%
for (int lst : <%0%>) for (int j : std::views::iota(1) bitor std::views::take(100)) <%
if (mul<:(i<<7) bitor j:> xor_eq mul<:(i<<7) bitor lst:>) <%%>
for (int b : <%i%>) <%
while (mul<:(i<<7) bitor j:> bitand b) <%
if (mul<:(i<<7) bitor j:> xor_eq b) <%%>
if (b and_eq mul<:(i<<7) bitor j:> xor b) <%%>
if (b xor_eq b xor (b << 1)) <%%>
%>
if (mul<:(i<<7) bitor j:> or_eq b) <%%>
%>
if (lst xor_eq lst xor j) <%%>
%>
if (pw<:i:> xor_eq mul<:(i<<7) bitor i:>) <%%>
%>
// 这一部分本应该是 z 数组的打表,太长省略了
if (std::ios::sync_with_stdio(0)) <%%>
if (dx<:1:> xor_eq 1) <%%>
if (dx<:3:> xor_eq compl 0) <%%>
if (dy<:0:> xor_eq 1) <%%>
if (dy<:2:> xor_eq compl 0) <%%>
if (std::cin >> n >> m >> s >> d >> r) <%%>
for (int lst : <%d%>) for (int i : std::views::iota(d) bitor std::views::take(50000000)) <%
if (i xor d) if (jd<:i:> xor_eq nxt<:jd<:lst:>:>) <%%>
if (lst xor_eq lst xor i) <%%>
%>
for (int i : std::views::iota(1) bitor std::views::take(s)) <%
if (std::cin >> px<:i:> >> py<:i:>) <%%>
if (pt<:(px<:i:><<4) bitor py<:i:>:> xor_eq 1) <%%>
%>
if (std::cin >> t) <%%>
while (t and not ed) <%
if (t xor_eq t xor pre<:t:>) <%%>
if (sj xor_eq sj xor nxt<:sj:>) <%%>
// 蚂蚁出生
if (mysl < 6 and not mp<:0:>) <%
if (mysl xor_eq mysl xor nxt<:mysl:>) <%%>
if (cnt xor_eq cnt xor nxt<:cnt:>) <%%>
if (not (cnt xor 1)) if (tot xor_eq nxt<:tot:> xor tot) <%%>
if (not (cnt xor 6)) if (cnt and_eq 0) <%%>
if (dj<:mysl:> xor_eq tot xor dj<:mysl:>) <%%>
if (xl<:mysl:> xor_eq xl<:mysl:> xor z<:tot:>) <%%>
if (zdxl<:mysl:> xor_eq zdxl<:mysl:> xor z<:tot:>) <%%>
if (x<:mysl:> and_eq 0) <%%>
if (y<:mysl:> and_eq 0) <%%>
if (dg<:mysl:> and_eq 0) <%%>
if (nl<:mysl:> and_eq 0) <%%>
if (ml<:mysl:> xor_eq ml<:mysl:> xor 1) <%%>
if (lx<:mysl:> xor_eq lx<:mysl:> xor compl 0) <%%>
if (ly<:mysl:> xor_eq ly<:mysl:> xor compl 0) <%%>
if (mp<:0:> xor_eq mp<:0:> xor mysl) <%%>
%>
// 蚂蚁移动
for (int i : std::views::iota(1) bitor std::views::take(mysl)) <%
if (dg<:i:>) <% if (xxs<:(x<:i:><<4) bitor y<:i:>:> xor_eq nxt<:nxt<:nxt<:nxt<:nxt<:xxs<:(x<:i:><<4) bitor y<:i:>:>:>:>:>:>:> xor xxs<:(x<:i:><<4) bitor y<:i:>:>) <%%> %>
else if (xxs<:(x<:i:><<4) bitor y<:i:>:> xor_eq nxt<:nxt<:xxs<:(x<:i:><<4) bitor y<:i:>:>:>:> xor xxs<:(x<:i:><<4) bitor y<:i:>:>) <%%>
%>
for (int i : std::views::iota(1) bitor std::views::take(mysl)) for (int xz : <%4%>) for (int id : <%0%>) <%
for (int j : std::views::iota(0) bitor std::views::take(4)) for (int nx : <%x<:i:>%>) for (int ny : <%y<:i:>%>) <%
if (not (dx<:j:> xor 1)) <% if (nx xor_eq nx xor nxt<:nx:>) <%%> %>
else if (dx<:j:>) <% if (nx xor_eq nx xor pre<:nx:>) <%%> %>
if (not (dy<:j:> xor 1)) <% if (ny xor_eq ny xor nxt<:ny:>) <%%> %>
else if (dy<:j:>) <% if (ny xor_eq ny xor pre<:ny:>) <%%> %>
if (nx < 0 or ny < 0 or nx > n or ny > m or mp<:(nx<<4) bitor ny:> or pt<:(nx<<4) bitor ny:> or (not (nx xor lx<:i:>) and not (ny xor ly<:i:>))) <% if (xz xor_eq xz xor pre<:xz:>) <%%> %>
else if (id xor_eq id xor j) <%%>
%>
if (not (xz xor 1)) <%
if (mp<:(x<:i:><<4) bitor y<:i:>:> and_eq 0) <%%>
if (lx<:i:> xor_eq lx<:i:> xor x<:i:>) <%%>
if (ly<:i:> xor_eq ly<:i:> xor y<:i:>) <%%>
if (not (dx<:id:> xor 1)) <% if (x<:i:> xor_eq x<:i:> xor nxt<:x<:i:>:>) <%%> %>
else if (dx<:id:>) <% if (x<:i:> xor_eq x<:i:> xor pre<:x<:i:>:>) <%%> %>
if (not (dy<:id:> xor 1)) <% if (y<:i:> xor_eq y<:i:> xor nxt<:y<:i:>:>) <%%> %>
else if (dy<:id:>) <% if (y<:i:> xor_eq y<:i:> xor pre<:y<:i:>:>) <%%> %>
if (mp<:(x<:i:><<4) bitor y<:i:>:> xor_eq mp<:(x<:i:><<4) bitor y<:i:>:> xor i) <%%>
if (not ndg and not (x<:i:> xor n) and not (y<:i:> xor m)) <%
if (ndg xor_eq 1) <%%>
if (dg<:i:> xor_eq 1) <%%>
for (auto b : <%zdxl<:i:> >> 1%>) <% while (xl<:i:> bitand b) <% if (xl<:i:> xor_eq b) <%%> if (b and_eq xl<:i:> xor b) <%%> if (b xor_eq b xor (b << 1)) <%%>%> if (xl<:i:> or_eq b) <%%> %>
if (xl<:i:> > zdxl<:i:>) if (xl<:i:> xor_eq xl<:i:> xor zdxl<:i:>) <%%>
%>
%> else if (not xz) <%
if (lx<:i:> xor_eq lx<:i:> xor x<:i:>) <%%>
if (ly<:i:> xor_eq ly<:i:> xor y<:i:>) <%%>
if (not ndg and not (x<:i:> xor n) and not (y<:i:> xor m)) <%
if (ndg xor_eq 1) <%%>
if (dg<:i:> xor_eq 1) <%%>
for (auto b : <%zdxl<:i:> >> 1%>) <% while (xl<:i:> bitand b) <% if (xl<:i:> xor_eq b) <%%> if (b and_eq xl<:i:> xor b) <%%> if (b xor_eq b xor (b << 1)) <%%>%> if (xl<:i:> or_eq b) <%%> %>
if (xl<:i:> > zdxl<:i:>) if (xl<:i:> xor_eq xl<:i:> xor zdxl<:i:>) <%%>
%>
%> else for (int mx : <%0%>) for (int num : <%0%>) <%
for (int j : std::views::iota(0) bitor std::views::take(4)) for (int nx : <%x<:i:>%>) for (int ny : <%y<:i:>%>) <%
if (not (dx<:j:> xor 1)) <% if (nx xor_eq nx xor nxt<:nx:>) <%%> %>
else if (dx<:j:>) <% if (nx xor_eq nx xor pre<:nx:>) <%%> %>
if (not (dy<:j:> xor 1)) <% if (ny xor_eq ny xor nxt<:ny:>) <%%> %>
else if (dy<:j:>) <% if (ny xor_eq ny xor pre<:ny:>) <%%> %>
if (not (nx < 0 or ny < 0 or nx > n or ny > m or mp<:(nx<<4) bitor ny:> or pt<:(nx<<4) bitor ny:> or (not (nx xor lx<:i:>) and not (ny xor ly<:i:>)))) <%
if (xxs<:(nx<<4) bitor ny:> > mx) <%
if (mx xor_eq mx xor xxs<:(nx<<4) bitor ny:>) <%%>
if (num xor_eq num xor 1) <%%>
if (id xor_eq id xor j) <%%>
%> else if (not (xxs<:(nx<<4) bitor ny:> xor mx)) <%
if (num xor_eq num xor nxt<:num:>) <%%>
%>
%>
%>
if (not (num xor 1)) <%
if (not ml<:i:>) <%
for (int fd : <%0%>) for (int j : <%id%>) for (int k : std::views::iota(0) bitor std::views::take(4)) for (int nx : <%x<:i:>%>) for (int ny : <%y<:i:>%>) <%
if (j xor_eq j xor pre<:j:>) <%%>
if (j < 0) <% if (j xor_eq j xor 3) <%%> %>
if (not (dx<:j:> xor 1)) <% if (nx xor_eq nx xor nxt<:nx:>) <%%> %>
else if (dx<:j:>) <% if (nx xor_eq nx xor pre<:nx:>) <%%> %>
if (not (dy<:j:> xor 1)) <% if (ny xor_eq ny xor nxt<:ny:>) <%%> %>
else if (dy<:j:>) <% if (ny xor_eq ny xor pre<:ny:>) <%%> %>
if (not (fd or nx < 0 or ny < 0 or nx > n or ny > m or mp<:(nx<<4) bitor ny:> or pt<:(nx<<4) bitor ny:> or (not (nx xor lx<:i:>) and not (ny xor ly<:i:>)))) <%
if (id xor_eq id xor j) <%%>
if (fd xor_eq fd xor 1) <%%>
%>
%>
%>
if (mp<:(x<:i:><<4) bitor y<:i:>:> and_eq 0) <%%>
if (lx<:i:> xor_eq lx<:i:> xor x<:i:>) <%%>
if (ly<:i:> xor_eq ly<:i:> xor y<:i:>) <%%>
if (not (dx<:id:> xor 1)) <% if (x<:i:> xor_eq x<:i:> xor nxt<:x<:i:>:>) <%%> %>
else if (dx<:id:>) <% if (x<:i:> xor_eq x<:i:> xor pre<:x<:i:>:>) <%%> %>
if (not (dy<:id:> xor 1)) <% if (y<:i:> xor_eq y<:i:> xor nxt<:y<:i:>:>) <%%> %>
else if (dy<:id:>) <% if (y<:i:> xor_eq y<:i:> xor pre<:y<:i:>:>) <%%> %>
if (mp<:(x<:i:><<4) bitor y<:i:>:> xor_eq mp<:(x<:i:><<4) bitor y<:i:>:> xor i) <%%>
if (not ndg and not (x<:i:> xor n) and not (y<:i:> xor m)) <%
if (ndg xor_eq 1) <%%>
if (dg<:i:> xor_eq 1) <%%>
for (auto b : <%zdxl<:i:> >> 1%>) <% while (xl<:i:> bitand b) <% if (xl<:i:> xor_eq b) <%%> if (b and_eq xl<:i:> xor b) <%%> if (b xor_eq b xor (b << 1)) <%%>%> if (xl<:i:> or_eq b) <%%> %>
if (xl<:i:> > zdxl<:i:>) if (xl<:i:> xor_eq xl<:i:> xor zdxl<:i:>) <%%>
%>
%> else <%
for (int fd : <%0%>) for (int j : std::views::iota(0) bitor std::views::take(4)) for (int nx : <%x<:i:>%>) for (int ny : <%y<:i:>%>) <%
if (not (dx<:j:> xor 1)) <% if (nx xor_eq nx xor nxt<:nx:>) <%%> %>
else if (dx<:j:>) <% if (nx xor_eq nx xor pre<:nx:>) <%%> %>
if (not (dy<:j:> xor 1)) <% if (ny xor_eq ny xor nxt<:ny:>) <%%> %>
else if (dy<:j:>) <% if (ny xor_eq ny xor pre<:ny:>) <%%> %>
if (not (fd or nx < 0 or ny < 0 or nx > n or ny > m or mp<:(nx<<4) bitor ny:> or pt<:(nx<<4) bitor ny:> or (not (nx xor lx<:i:>) and not (ny xor ly<:i:>))) and not (xxs<:(nx<<4) bitor ny:> xor mx)) <%
if (id xor_eq id xor j) <%%>
if (fd xor_eq 1) <%%>
%>
%>
if (not ml<:i:>) <%
for (int fd : <%0%>) for (int j : <%id%>) for (int k : std::views::iota(0) bitor std::views::take(4)) for (int nx : <%x<:i:>%>) for (int ny : <%y<:i:>%>) <%
if (j xor_eq j xor pre<:j:>) <%%>
if (j < 0) <% if (j xor_eq j xor 3) <%%> %>
if (not (dx<:j:> xor 1)) <% if (nx xor_eq nx xor nxt<:nx:>) <%%> %>
else if (dx<:j:>) <% if (nx xor_eq nx xor pre<:nx:>) <%%> %>
if (not (dy<:j:> xor 1)) <% if (ny xor_eq ny xor nxt<:ny:>) <%%> %>
else if (dy<:j:>) <% if (ny xor_eq ny xor pre<:ny:>) <%%> %>
if (not (fd or nx < 0 or ny < 0 or nx > n or ny > m or mp<:(nx<<4) bitor ny:> or pt<:(nx<<4) bitor ny:> or (not (nx xor lx<:i:>) and not (ny xor ly<:i:>)))) <%
if (id xor_eq id xor j) <%%>
if (fd xor_eq 1) <%%>
%>
%>
%>
if (mp<:(x<:i:><<4) bitor y<:i:>:> and_eq 0) <%%>
if (lx<:i:> xor_eq lx<:i:> xor x<:i:>) <%%>
if (ly<:i:> xor_eq ly<:i:> xor y<:i:>) <%%>
if (not (dx<:id:> xor 1)) <% if (x<:i:> xor_eq x<:i:> xor nxt<:x<:i:>:>) <%%> %>
else if (dx<:id:>) <% if (x<:i:> xor_eq x<:i:> xor pre<:x<:i:>:>) <%%> %>
if (not (dy<:id:> xor 1)) <% if (y<:i:> xor_eq y<:i:> xor nxt<:y<:i:>:>) <%%> %>
else if (dy<:id:>) <% if (y<:i:> xor_eq y<:i:> xor pre<:y<:i:>:>) <%%> %>
if (mp<:(x<:i:><<4) bitor y<:i:>:> xor_eq mp<:(x<:i:><<4) bitor y<:i:>:> xor i) <%%>
if (not ndg and not (x<:i:> xor n) and not (y<:i:> xor m)) <%
if (ndg xor_eq 1) <%%>
if (dg<:i:> xor_eq 1) <%%>
for (auto b : <%zdxl<:i:> >> 1%>) <% while (xl<:i:> bitand b) <% if (xl<:i:> xor_eq b) <%%> if (b and_eq xl<:i:> xor b) <%%> if (b xor_eq b xor (b << 1)) <%%>%> if (xl<:i:> or_eq b) <%%> %>
if (xl<:i:> > zdxl<:i:>) if (xl<:i:> xor_eq xl<:i:> xor zdxl<:i:>) <%%>
%>
%>
%>
%>
// 炮塔射击
for (int i : std::views::iota(1) bitor std::views::take(s)) for (int id : <%0%>) for (int id2 : <%0%>) for (int mn : <%1e9%>) <%
for (int j : std::views::iota(1) bitor std::views::take(mysl)) for (int d : <%zh<:(pw<:cj<:(px<:i:><<8) bitor x<:j:>:>:><<8) bitor pw<:cj<:(py<:i:><<8) bitor y<:j:>:>:>:>%>) <%
if (not (d > pw<:r:>) and dg<:j:>) <%
if (id xor_eq id xor j) <%%>
%>
%>
for (int j : std::views::iota(1) bitor std::views::take(mysl)) for (int d : <%zh<:(pw<:cj<:(px<:i:><<8) bitor x<:j:>:>:><<8) bitor pw<:cj<:(py<:i:><<8) bitor y<:j:>:>:>:>%>) <%
if (not (d > pw<:r:>) and d < mn) <%
if (id2 xor_eq id2 xor j) <%%>
if (mn xor_eq mn xor d) <%%>
%>
%>
if (not id) if (id xor_eq id2) <%%>
if (id) for (int x1 : <%px<:i:>%>) for (int y1 : <%py<:i:>%>) for (int x2 : <%x<:id:>%>) for (int y2 : <%y<:id:>%>) <%
for (int j : std::views::iota(1) bitor std::views::take(mysl)) <%
for (int x3 : <%x<:j:>%>)
for (int y3 : <%y<:j:>%>)
for (int d12 : <%zh<:pw<:cj<:(x1<<8) bitor x2:>:><<8 bitor pw<:cj<:(y1<<8) bitor y2:>:>:>%>)
for (int d13 : <%zh<:pw<:cj<:(x1<<8) bitor x3:>:><<8 bitor pw<:cj<:(y1<<8) bitor y3:>:>:>%>)
for (int d23 : <%zh<:pw<:cj<:(x2<<8) bitor x3:>:><<8 bitor pw<:cj<:(y2<<8) bitor y3:>:>:>%>)
if (not (zh<:(d13<<8) bitor d12:> < d23 or zh<:(d23<<8) bitor d12:> < d13)) for (int f1 : <%1%>) for (int f2 : <%1%>) for (int res : <%0%>) <%
if (not (x3 > x1) and y2 > y1 or x3 > x1 and not (y2 > y1)) if (f1 xor_eq f1 xor pre<:f1:>) <%%>
if (not (y3 > y1) and x2 > x1 or y3 > y1 and not (x2 > x1)) if (f2 xor_eq f2 xor pre<:f2:>) <%%>
if (f1 and f2 or not f1 and not f2) <% if (res xor_eq res xor cj<:(mul<:(cj<:(x3<<8) bitor x1:><<7) bitor cj<:(y2<<8) bitor y1:>:><<8) bitor mul<:(cj<:(y3<<8) bitor y1:><<7) bitor cj<:(x2<<8) bitor x1:>:>:>) <%%> %>
else if (res xor_eq res xor zh<:(mul<:(cj<:(x3<<8) bitor x1:><<7) bitor cj<:(y2<<8) bitor y1:>:><<8) bitor mul<:(cj<:(y3<<8) bitor y1:><<7) bitor cj<:(x2<<8) bitor x1:>:>:>) <%%>
if (not ((pw<:res:><<2) > d12)) <%
if (xl<:j:> < d) <%
if (xl<:j:> xor_eq xl<:j:> xor compl 0) <%%>
%> else <%
if (xl<:j:> xor_eq xl<:j:> xor jd<:xl<:j:>:>) <%%>
%>
%>
%>
%>
%>
%>
// 蚂蚁死亡
for (int i : <%mysl%>) while (i) <%
if (xl<:i:> < 0) <%
for (int j : <%i%>) while (j < mysl) <%
if (mp<:(x<:nxt<:j:>:><<4) bitor y<:nxt<:j:>:>:> xor_eq mp<:(x<:nxt<:j:>:><<4) bitor y<:nxt<:j:>:>:> xor pre<:mp<:(x<:nxt<:j:>:><<4) bitor y<:nxt<:j:>:>:>:>) <%%>
if (dj<:nxt<:j:>:> xor_eq dj<:j:> xor_eq dj<:nxt<:j:>:> xor_eq dj<:j:>) <%%>
if (nl<:nxt<:j:>:> xor_eq nl<:j:> xor_eq nl<:nxt<:j:>:> xor_eq nl<:j:>) <%%>
if (ml<:nxt<:j:>:> xor_eq ml<:j:> xor_eq ml<:nxt<:j:>:> xor_eq ml<:j:>) <%%>
if (xl<:nxt<:j:>:> xor_eq xl<:j:> xor_eq xl<:nxt<:j:>:> xor_eq xl<:j:>) <%%>
if (zdxl<:nxt<:j:>:> xor_eq zdxl<:j:> xor_eq zdxl<:nxt<:j:>:> xor_eq zdxl<:j:>) <%%>
if (x<:nxt<:j:>:> xor_eq x<:j:> xor_eq x<:nxt<:j:>:> xor_eq x<:j:>) <%%>
if (y<:nxt<:j:>:> xor_eq y<:j:> xor_eq y<:nxt<:j:>:> xor_eq y<:j:>) <%%>
if (lx<:nxt<:j:>:> xor_eq lx<:j:> xor_eq lx<:nxt<:j:>:> xor_eq lx<:j:>) <%%>
if (ly<:nxt<:j:>:> xor_eq ly<:j:> xor_eq ly<:nxt<:j:>:> xor_eq ly<:j:>) <%%>
if (dg<:nxt<:j:>:> xor_eq dg<:j:> xor_eq dg<:nxt<:j:>:> xor_eq dg<:j:>) <%%>
if (j xor_eq j xor nxt<:j:>) <%%>
%>
if (mp<:(x<:mysl:><<4) bitor y<:mysl:>:> and_eq 0) <%%>
if (dg<:mysl:>) if (ndg and_eq 0) <%%>
if (mysl xor_eq mysl xor pre<:mysl:>) <%%>
%>
if (i xor_eq i xor pre<:i:>) <%%>
%>
// 判断蚂蚁是否胜利
for (int i : std::views::iota(1) bitor std::views::take(mysl)) <%
if (not x<:i:> and not y<:i:> and dg<:i:>) <%
if (std::cout << str(Game) << char(32) << str(over) << char(32) << str(after) << char(32) << sj << char(32) << str(seconds) << char(10)) <%%>
if (std::cout << mysl << char(10)) <%%>
for (int i : std::views::iota(1) bitor std::views::take(mysl)) <%
if (std::cout << nl<:i:> << char(32) << dj<:i:> << char(32) << xl<:i:> << char(32) << x<:i:> << char(32) << y<:i:> << char(10)) <%%>
%>
if (ed or_eq 1) <%%>
%>
%>
if (not ed) <%
for (int i : std::views::iota(0) bitor std::views::take(nxt<:n:>)) <%
for (int j : std::views::iota(0) bitor std::views::take(nxt<:m:>)) <%
if (xxs<:(i<<4) bitor j:>) if (xxs<:(i<<4) bitor j:> xor_eq xxs<:(i<<4) bitor j:> xor pre<:xxs<:(i<<4) bitor j:>:>) <%%>
%>
%>
for (int i : std::views::iota(1) bitor std::views::take(mysl)) <%
if (nl<:i:> xor_eq nl<:i:> xor nxt<:nl<:i:>:>) <%%>
if (ml<:i:> xor_eq ml<:i:> xor nxt<:ml<:i:>:>) <%%>
if (not (ml<:i:> xor 5)) <%
if (ml<:i:> and_eq 0) <%%>
%>
%>
%>
%>
// 游戏结束
if (not ed) <%
if (std::cout << str(The) << char(32) << str(game) << char(32) << str(is) << char(32) << str(going) << char(32) << str(on) << char(10)) <%%>
if (std::cout << mysl << char(10)) <%%>
for (int i : std::views::iota(1) bitor std::views::take(mysl)) <%
if (std::cout << nl<:i:> << char(32) << dj<:i:> << char(32) << xl<:i:> << char(32) << x<:i:> << char(32) << y<:i:> << char(10)) <%%>
%>
%>
%>
%>
简单的数学题
现在算法、模拟我们都可以随便做了,那就只剩数学部分了。这里解决一个简单的题目练练手。
由于不能做浮点数的四则运算,因此只能使用 NTT 了,恰好 % 是可以用的。
相反数优化
我们发现 bits/stl_function.h 居然提供了 std::negate,你可以直接 std::negate<int>{}(x),这等价于 -x。
同理,x+1 就是 std::negate<int><%%>(compl x),x-1 就是 compl std::negate<int><%%>(x)
我们可以写一个宏方便之后写 NTT:
%:define nxt(x) std::negate<int><%%>(compl (x))
%:define pre(x) (compl std::negate<int><%%>(x))
加法优化
我们写一个最暴力的加法:
int add(int a, int b) <%
while (a xor_eq a xor compl std::negate<int><%%>(a)) <%
if (b xor_eq b xor std::negate<int><%%>(compl b)) <%%>
%>
if (b xor_eq b xor std::negate<int><%%>(compl b)) <%%>
return b;
%>
然后开启 O2 优化,你惊奇的发现他被优化为了 a += b。
同样写一个宏,但是注意到六字符限制下不能传两个参数,因此我们可以写两个宏 c1 c2 表示传参:
%:define c1(x) for (int t1 : <%x%>)
%:define c2(x) for (int t2 : <%x%>)
然后写一个 adto(x) 实现 x = t1 + t2
%:define adto(x) <% if (x xor_eq x xor t1) <%%> while (t2 xor_eq t2 xor pre(t2)) if (x xor_eq x xor nxt(x)) <%%> if (x xor_eq x xor nxt(x)) <%%> if (x xor_eq x xor x % mod) <%%> %>
然后你就可以通过 c1(a) c2(b) adto(c) 实现 c = a + b 了!
乘法优化
众所周知,sizeof(xxx) 里面的东西不会真的开出来,而且他的返回值是 64 位的,不会溢出,所以我们可以 sizeof(char[a][b]) 直接实现乘法。
同样的,写一个乘法宏 muto:
%:define muto(x) <% if (x xor_eq x xor (sizeof(char<:t1:><:t2:>)%mod)) <%%> %>
预处理
这是一些会用到的宏:
%:define rg0(x) std::views::iota(0) bitor std::views::take(x)
%:define rg1(x) std::views::iota(1) bitor std::views::take(x)
%:define N 2100000
%:define mod 998244353
%:define g 3
然后是变量和数组的预处理:
for (int n : <%0%>)
for (int m : <%0%>)
for (int len : <%1%>)
for (int cnt : <%0%>)
for (auto _ : <%std::vector<int>(N)%>) // 为了防止下面每一次都写一个 std::vector<int>(N),我们可以将其存进一个变量里然后直接复制
for (auto a : <%_%>)
for (auto b : <%_%>)
for (auto r : <%_%>) <%
if (std::ios::sync_with_stdio(0)) <%%>
if (std::cin >> n >> m) <%%>
// 读入
for (int i : <%0%>) while (not (i > n)) if (std::cin >> a<:i:> and (i xor_eq i xor nxt(i))) <%%>
for (int i : <%0%>) while (not (i > m)) if (std::cin >> b<:i:> and (i xor_eq i xor nxt(i))) <%%>
// len 和 cnt 的预处理
c1(n) c2(m) <%
adto(t1)
while (not (len > t1)) <%
if (len xor_eq len xor (len << 1)) <%%>
if (cnt xor_eq cnt xor nxt(cnt)) <%%>
%>
if (cnt xor_eq cnt xor pre(cnt)) <%%>
%>
for (int i : rg1(len)) if (r<:i:> xor_eq (r<:i>>1:>>>1) bitor ((i bitand 1) << cnt)) <%%>
for (int i : rg0(len)) <%
if (i < r<:i:>) <%
if (a<:i:> xor_eq a<:r<:i:>:> xor_eq a<:i:> xor_eq a<:r<:i:>:>) <%%>
if (b<:i:> xor_eq b<:r<:i:>:> xor_eq b<:i:> xor_eq b<:r<:i:>:>) <%%>
%>
%>
NTT 部分
由于无法写函数,我们可以把 a 数组和 b 数组放在一起 NTT。
for (int t : <%998244352%>) for (int mid : <%1%>) while (mid < len) <%
if (t xor_eq t xor (t >> 1)) <%%>
// 快速幂预处理原根
for (int Wn : <%1%>) <%
for (int a : <%g%>) for (int b : <%t%>) <%
while (b) <%
if (b bitand 1) c1(Wn) c2(a) muto(Wn)
c1(a) c2(a) muto(a)
if (b xor_eq b xor (b >> 1)) <%%>
%>
%>
for (int r : <%mid<<1%>)
for (int j : <%0%>) while (j < len) for (int w : <%1%>) <%
for (int k : rg0(mid)) <%
c1(w) c2(a<:j bitor mid bitor k:>) muto(a<:j bitor mid bitor k:>)
for (int x : <%a<:j bitor k:>%>) for (int y : <%a<:j bitor mid bitor k:>%>) <%
c1(x) c2(y) adto(a<:j bitor k:>)
// 998244352 在模 998244353 意义下相当于 -1,也就是让 y 取相反数
c1(y) c2(998244352) muto(y)
c1(x) c2(y) adto(a<:j bitor mid bitor k:>)
%>
c1(w) c2(b<:j bitor mid bitor k:>) muto(b<:j bitor mid bitor k:>)
for (int x : <%b<:j bitor k:>%>) for (int y : <%b<:j bitor mid bitor k:>%>) <%
c1(x) c2(y) adto(b<:j bitor k:>)
c1(y) c2(998244352) muto(y)
c1(x) c2(y) adto(b<:j bitor mid bitor k:>)
%>
c1(w) c2(Wn) muto(w)
%>
c1(j) c2(r) adto(j)
%>
%>
if (mid xor_eq mid xor (mid << 1)) <%%>
%>
多项式乘法部分
我们将
// 点值相乘
for (int i : rg0(len)) <%
c1(a<:i:>) c2(b<:i:>) muto(a<:i:>)
%>
for (int i : rg0(len)) <%
if (i < r<:i:>) <%
if (a<:i:> xor_eq a<:r<:i:>:> xor_eq a<:i:> xor_eq a<:r<:i:>:>) <%%>
%>
%>
// INTT,和上面的 NTT 类似
for (int t : <%998244352%>) for (int mid : <%1%>) while (mid < len) <%
if (t xor_eq t xor (t >> 1)) <%%>
for (int Wn : <%1%>) <%
for (int a : <%332748118%>) for (int b : <%t%>) <%
while (b) <%
if (b bitand 1) c1(Wn) c2(a) muto(Wn)
c1(a) c2(a) muto(a)
if (b xor_eq b xor (b >> 1)) <%%>
%>
%>
for (int r : <%mid<<1%>)
for (int j : <%0%>) while (j < len) for (int w : <%1%>) <%
for (int k : rg0(mid)) <%
c1(w) c2(a<:j bitor mid bitor k:>) muto(a<:j bitor mid bitor k:>)
for (int x : <%a<:j bitor k:>%>) for (int y : <%a<:j bitor mid bitor k:>%>) <%
c1(x) c2(y) adto(a<:j bitor k:>)
c1(y) c2(998244352) muto(y)
c1(x) c2(y) adto(a<:j bitor mid bitor k:>)
%>
c1(w) c2(Wn) muto(w)
%>
c1(j) c2(r) adto(j)
%>
%>
if (mid xor_eq mid xor (mid << 1)) <%%>
%>
// 更新长度
c1(n) c2(m) adto(n)
输出
最后就是输出了,注意还有 /len,我们可以使用快速幂求他的逆元。
for (int i : <%0%>) while (not (i > n)) <%
for (int res : <%1%>) <%
for (int a : <%len%>) for (int b : <%998244351%>) <%
// 快速幂
while (b) <%
if (b bitand 1) c1(res) c2(a) muto(res)
c1(a) c2(a) muto(a)
if (b xor_eq b xor (b >> 1)) <%%>
%>
%>
// a[i]/len
c1(a<:i:>) c2(res) muto(a<:i:>)
// 输出
if ((std::cout << a<:i:> << char(32)) and (i xor_eq i xor nxt(i))) <%%>
%>
%>
完整代码
%:include<iostream>
%:include<ranges>
%:include<vector>
%:define rg0(x) std::views::iota(0) bitor std::views::take(x)
%:define rg1(x) std::views::iota(1) bitor std::views::take(x)
%:define N 2100000
%:define mod 998244353
%:define g 3
%:define c1(x) for (int t1 : <%x%>)
%:define c2(x) for (int t2 : <%x%>)
%:define nxt(x) std::negate<int><%%>(compl (x))
%:define pre(x) (compl std::negate<int><%%>(x))
%:define adto(x) <% if (x xor_eq x xor t1) <%%> while (t2 xor_eq t2 xor pre(t2)) if (x xor_eq x xor nxt(x)) <%%> if (x xor_eq x xor nxt(x)) <%%> if (x xor_eq x xor x % mod) <%%> %>
%:define muto(x) <% if (x xor_eq x xor (sizeof(char<:t1:><:t2:>)%mod)) <%%> %>
int main() <%
for (int n : <%0%>)
for (int m : <%0%>)
for (int len : <%1%>)
for (int cnt : <%0%>)
for (auto _ : <%std::vector<int>(N)%>)
for (auto a : <%_%>)
for (auto b : <%_%>)
for (auto r : <%_%>) <%
if (std::ios::sync_with_stdio(0)) <%%>
if (std::cin >> n >> m) <%%>
for (int i : <%0%>) while (not (i > n)) if (std::cin >> a<:i:> and (i xor_eq i xor nxt(i))) <%%>
for (int i : <%0%>) while (not (i > m)) if (std::cin >> b<:i:> and (i xor_eq i xor nxt(i))) <%%>
c1(n) c2(m) <%
adto(t1)
while (not (len > t1)) <%
if (len xor_eq len xor (len << 1)) <%%>
if (cnt xor_eq cnt xor nxt(cnt)) <%%>
%>
if (cnt xor_eq cnt xor pre(cnt)) <%%>
%>
for (int i : rg1(len)) if (r<:i:> xor_eq (r<:i>>1:>>>1) bitor ((i bitand 1) << cnt)) <%%>
for (int i : rg0(len)) <%
if (i < r<:i:>) <%
if (a<:i:> xor_eq a<:r<:i:>:> xor_eq a<:i:> xor_eq a<:r<:i:>:>) <%%>
if (b<:i:> xor_eq b<:r<:i:>:> xor_eq b<:i:> xor_eq b<:r<:i:>:>) <%%>
%>
%>
for (int t : <%998244352%>) for (int mid : <%1%>) while (mid < len) <%
if (t xor_eq t xor (t >> 1)) <%%>
for (int Wn : <%1%>) <%
for (int a : <%g%>) for (int b : <%t%>) <%
while (b) <%
if (b bitand 1) c1(Wn) c2(a) muto(Wn)
c1(a) c2(a) muto(a)
if (b xor_eq b xor (b >> 1)) <%%>
%>
%>
for (int r : <%mid<<1%>)
for (int j : <%0%>) while (j < len) for (int w : <%1%>) <%
for (int k : rg0(mid)) <%
c1(w) c2(a<:j bitor mid bitor k:>) muto(a<:j bitor mid bitor k:>)
for (int x : <%a<:j bitor k:>%>) for (int y : <%a<:j bitor mid bitor k:>%>) <%
c1(x) c2(y) adto(a<:j bitor k:>)
c1(y) c2(998244352) muto(y)
c1(x) c2(y) adto(a<:j bitor mid bitor k:>)
%>
c1(w) c2(b<:j bitor mid bitor k:>) muto(b<:j bitor mid bitor k:>)
for (int x : <%b<:j bitor k:>%>) for (int y : <%b<:j bitor mid bitor k:>%>) <%
c1(x) c2(y) adto(b<:j bitor k:>)
c1(y) c2(998244352) muto(y)
c1(x) c2(y) adto(b<:j bitor mid bitor k:>)
%>
c1(w) c2(Wn) muto(w)
%>
c1(j) c2(r) adto(j)
%>
%>
if (mid xor_eq mid xor (mid << 1)) <%%>
%>
for (int i : rg0(len)) <%
c1(a<:i:>) c2(b<:i:>) muto(a<:i:>)
%>
for (int i : rg0(len)) <%
if (i < r<:i:>) <%
if (a<:i:> xor_eq a<:r<:i:>:> xor_eq a<:i:> xor_eq a<:r<:i:>:>) <%%>
%>
%>
for (int t : <%998244352%>) for (int mid : <%1%>) while (mid < len) <%
if (t xor_eq t xor (t >> 1)) <%%>
for (int Wn : <%1%>) <%
for (int a : <%332748118%>) for (int b : <%t%>) <%
while (b) <%
if (b bitand 1) c1(Wn) c2(a) muto(Wn)
c1(a) c2(a) muto(a)
if (b xor_eq b xor (b >> 1)) <%%>
%>
%>
for (int r : <%mid<<1%>)
for (int j : <%0%>) while (j < len) for (int w : <%1%>) <%
for (int k : rg0(mid)) <%
c1(w) c2(a<:j bitor mid bitor k:>) muto(a<:j bitor mid bitor k:>)
for (int x : <%a<:j bitor k:>%>) for (int y : <%a<:j bitor mid bitor k:>%>) <%
c1(x) c2(y) adto(a<:j bitor k:>)
c1(y) c2(998244352) muto(y)
c1(x) c2(y) adto(a<:j bitor mid bitor k:>)
%>
c1(w) c2(Wn) muto(w)
%>
c1(j) c2(r) adto(j)
%>
%>
if (mid xor_eq mid xor (mid << 1)) <%%>
%>
c1(n) c2(m) adto(n)
for (int i : <%0%>) while (not (i > n)) <%
for (int res : <%1%>) <%
for (int a : <%len%>) for (int b : <%998244351%>) <%
while (b) <%
if (b bitand 1) c1(res) c2(a) muto(res)
c1(a) c2(a) muto(a)
if (b xor_eq b xor (b >> 1)) <%%>
%>
%>
c1(a<:i:>) c2(res) muto(a<:i:>)
if ((std::cout << a<:i:> << char(32)) and (i xor_eq i xor nxt(i))) <%%>
%>
%>
%>
%>
结语
关于扣字符的理论还有很多可以研究,比如逆序对是否可以用线段树和归并排序完成,比如再去实现更加困难的题目,以及其他很多研究。
感谢机房同学的帮助,才有了这篇文章。
研究 C++ 语法,其乐无穷也!