如何科学膜拜

· · 休闲·娱乐

观前提示:本文纯属娱乐,可能有部分不严谨之处,请勿深究,亦请勿将本文作为学习资料。

本文是在 NOIP 2025 前开始写的,在这里宣传我的 NOIP 2025 游记。

首先,由于 wtc 非常强,所以这里我们膜拜 wtc。

那怎么膜拜呢?

%%%wtc 显然是不够的,我们需要用一个程序来膜拜 wtc。

#include<cstdio>
int main()
{
    printf("%%%wtc");
}

诶怎么编译器弹警告了?原来 %printf 转换说明符的前导字符,为了使一个 % 表示一个 % 而不是两个 % 表示一个 %,我们改用 cout 输出:

#include<iostream>
using namespace std;
int main()
{
    cout<<"%%%wtc"<<endl;
}

膜拜次数:0

诶,为什么是 0?既然我们都是 OIer,应该都能接受 0 标号。这里根据传统,我们对每行 %%%wtc 采用 0 标号,也就是说,我们输出的最后一行是0

所以我们的“膜拜次数”实际上指的是最后一次膜拜的行号。

显然膜拜一次难以表示我们的热情,所以我们可以膜拜很多次:

#include<iostream>
using namespace std;
int main()
{
    cout<<"%%%wtc"<<endl;
    cout<<"%%%wtc"<<endl;
    cout<<"%%%wtc"<<endl;
    cout<<"%%%wtc"<<endl;
    cout<<"%%%wtc"<<endl;
}

膜拜次数:4

显然这样我们膜拜的次数还是太少了,于是我们可以用一个循环进行膜拜:

#include<iostream>
using namespace std;
int main()
{
    for(int i=1;i<=100000;i++)
    cout<<"%%%wtc"<<endl;
}

膜拜次数:99999

既然都膜拜这么多次了,那干脆直接无限膜拜不就好了吗?

说干就干:

#include<iostream>
using namespace std;
int main()
{
    while(1)
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\infty

这里的膜拜次数写 \infty 显然太低级了。作为经历过「最长待机」的人,显然可以把膜拜次数写成 \omega

膜拜次数:\omega

这样看起来虽然高级多了,但是好像不太符合“膜拜次数”的定义?(毕竟此时,“最后一行”都不存在)

让我们更改一下我们的代码:

#include<iostream>
using namespace std;
int main()
{
    while(1)
    cout<<"%%%wtc"<<endl;//对应有限序数 0,1,2,3,4,...
    cout<<"%%%wtc"<<endl;//对应序数 omega:大于所有有限序数的最小序数
}

膜拜次数:\omega

这下对劲多了。

显然还能有更多的膜拜!

#include<iostream>
using namespace std;
int main()
{
    while(1)
    cout<<"%%%wtc"<<endl;
    for(int i=1;i<=100000;i++)
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega+99999

太少了,来个 \omega+\omega 如何?

#include<iostream>
using namespace std;
int main()
{
    while(1)
    cout<<"%%%wtc"<<endl;
    while(1)
    cout<<"%%%wtc"<<endl;
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega\times2

这里的乘法就是正常的乘法。

显然还能有更多的膜拜!

#include<iostream>
using namespace std;
int main()
{
    for(int i=1;i<=100000;i++)
    while(1)
    cout<<"%%%wtc"<<endl;
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega\times100000

显然还能有更多的膜拜!

#include<iostream>
using namespace std;
int main()
{
    while(1)
    while(1)
    cout<<"%%%wtc"<<endl;
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega^2

这里的乘方就是正常的乘方。

显然还能有更多的膜拜!

#include<iostream>
using namespace std;
int main()
{
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    cout<<"%%%wtc"<<endl;
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega^{10}

考虑到大量 while(1) 会使得代码不美观,我们换一种方式表示 \omega 高次幂的膜拜:

#include<iostream>
using namespace std;
void mo_bai(int x)
{
    if(x==0)
    cout<<"%%%wtc"<<endl;
    else
    while(1)
    mo_bai(x-1);
}
int main()
{
    mo_bai(100000);
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega^{100000}

但是好像卡住了?

如何才能制造出比 \omega 的有限次方更多的膜拜呢?

可以想到一件事情:我们只需要输出一个无限膜拜序列,第一项是 \omega,第二项是 \omega^2,第三项是 \omega^3,以此类推,不就可以了吗?

说干就干!

但是你会悲伤地发现 C++ 的整型都是有上限的……

如果我们套用上面的做法,我们就需要手写一份无上限的高精度整型,太麻烦了,考虑更简单的做法。

通过若干人类智慧,我们可以得到以下代码:

#include<iostream>
#include<functional>
using namespace std;
int main()
{
    function<void()> las=[]()->void{cout<<"%%%wtc"<<endl;};
    while(1)
    {
        auto s=[las]()->void{while(1)las();};
        las=s;
        las();//第 x 次执行 while 循环的时候会 las() 就对应 omega^x 次膜拜
    }
    //while 循环执行过程中 x 会大于任何有限数,所以我们认为 omega 的指数是 omega
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega^{\omega}

至此,我们已经超越了「最长待机」中可能涉及的所有序数。

但是,显然这个还可以继续升级!

#include<iostream>
#include<functional>
using namespace std;
int main()
{
    function<void()> las=[]()->void{cout<<"%%%wtc"<<endl;};
    while(1)
    {
        auto s=[las]()->void{while(1)las();};
        las=s;
        las();
    }
    while(1)
    {
        auto s=[las]()->void{while(1)las();};
        las=s;
        las();
    }
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega^{\omega\times2}

进一步优化:

#include<iostream>
#include<functional>
using namespace std;
int main()
{
    function<void()> las=[]()->void{cout<<"%%%wtc"<<endl;};
    for(int i=1;i<=100000;i++)
    while(1)
    {
        auto s=[las]()->void{while(1)las();};
        las=s;
        las();
    }
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega^{\omega\times100000}

叠叠幂塔是好事,所以开始叠幂塔:

#include<iostream>
#include<functional>
using namespace std;
int main()
{
    function<void()> las=[]()->void{cout<<"%%%wtc"<<endl;};
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    while(1)
    {
        auto s=[las]()->void{while(1)las();};
        las=s;
        las();
    }
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega^{\omega^{10}}

注意,正常情况下(就是指没有括号的情况下),幂塔是从上往下计算的。

同样可以将 while 循环改用递归:

#include<iostream>
#include<functional>
using namespace std;
void mo_bai(int n,function<void()> &las)
{
    if(n==0)
    {
        auto s=[las]()->void{while(1)las();};
        las=s;
        las();
    }
    else
    while(1)
    mo_bai(n-1,las);
}
int main()
{
    function<void()> las=[]()->void{cout<<"%%%wtc"<<endl;};
    mo_bai(100000,las);
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega^{\omega^{100000}}

但是怎么样才能使答案来到 \omega^{\omega^{\omega}} 呢?

再来考虑一些人类智慧:我们可以复用我们已经得出的做法。

于是我们就可以得到这份抽象代码:

#include<iostream>
#include<functional>
using namespace std;
int main()
{
    function<void()> inner_las=[]()->void{cout<<"%%%wtc"<<endl;};
    function<void()> las=[&inner_las]()->void{while(1){auto s=[inner_las]()->void{while(1)inner_las();};inner_las=s;inner_las();}/*这个 while 循环了几次膜拜次数就是 omega 的几次幂*/};
    while(1)
    {
        auto s=[las]()->void{while(1)las();};
        las=s;
        las();
    }
    //通过已有的构造使上面那个 while 的执行次数达到 omega^omega
    cout<<"%%%wtc"<<endl;//最终的膜拜次数来到了 omega^omega^omega
}

膜拜次数:\omega^{\omega^{\omega}}

通过套娃还可以更进一步:

#include<iostream>
#include<functional>
using namespace std;
int main()
{
    function<void()> las1=[]()->void{cout<<"%%%wtc"<<endl;};
    function<void()> las2=[&las1]()->void{while(1){auto s=[las1]()->void{while(1)las1();};las1=s;las1();}};
    function<void()> las3=[&las2]()->void{while(1){auto s=[las2]()->void{while(1)las2();};las2=s;las2();}};
    while(1)
    {
        auto s=[las3]()->void{while(1)las3();};
        las3=s;
        las3();
    }
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\omega^{\omega^{\omega^{\omega}}}

明显到了这一步,我们想叠几层幂塔就能叠几层。

为什么不直接叠个无限层呢?

说干就干:

#include<iostream>
#include<functional>
using namespace std;
int main()
{
    function<void()> ss=[]()->void{cout<<"%%%wtc"<<endl;};
    while(1)
    {
        function<void()> las=ss;
        ss=[las]()mutable->void{while(1){auto s=[las]()->void{while(1)las();};las=s;las();}};
        ss();//第 x 次执行 while 循环时 ss 就是 omega 的 x+1 层幂塔
    }
    cout<<"%%%wtc"<<endl;
}

膜拜次数:\varepsilon_0

怎么膜拜次数变成神秘符号了?没事,这里给出定义:\varepsilon_0 是使得 \omega^{x}=x 的最小序数 x,也是数列 \omega,\omega^{\omega},\omega^{\omega^{\omega}},\omega^{\omega^{\omega^{\omega}}},\dots 的极限。

所以你可以吧 \varepsilon_0 理解为 \omega 的无限幂塔。

虽然膜拜次数还能更多,但是考虑到我们的代码其实已经写得很抽象了,所以我们也就不再继续写了,本文也就先告一段落了。

P.S. 如果觉得现在运气不好的话可以复制这里的最后一份代码进行膜拜(当然膜拜的对象可以改成任何你认为很强的人),运气会瞬间补满!