欢迎光临散文网 会员登陆 & 注册

用 batch 解决小问题

2023-07-31 09:44 作者:Ryan璃黯  | 我要投稿

个人博客:https://原子核.eu.org/

我在大同一中初中举办的所谓 “求知杯” 的竞赛里,看到了一道很霸道的题。当时是第 6 题,题目内容是:

将集合 {1, 2, ……, 19} 中每两个互异的数作乘积,所有这种乘积的和为______.

很明显这道题可以通过强攻硬算做出来,当时也的确有人这么做,那个人算出来的结果和电脑算出来的结果非常相近。于是我开始考虑用编程实现大量计算。学校电脑没有 g++,所以我选了最基础的 batch(批处理)来编写。

根据题意,我们需要计算一些乘数有规律的乘法,它们分别是:(Bilibili没有代码块,姑且用引用块低配平替一下)

1×2=
1×3=
……
1×19=
……
2×3=
2×4=
……
2×19=
……
17×18=
18×19=

为了计算方便,我们假设两个乘数分别是变量 t1t2。建立这两个变量:

set t1=
set t2=
set /a t1=1
set /a t2=%t1%+1
::定义t1=1,t2=2

这样我们就得到了两个变量,分别是 t1==1t2=2

之后,我们还需要一个用于存放每一步的结果的变量 tmp 和用于累加结果的变量 num。建立这两个变量:

set num=
set /a num=0 
set tmp=0

我们需要两个乘数依次滚动,在将每个【第一个乘数】所对应的【第二个乘数】遍历。为此我们需要两层循环。小循环是【第二个乘数】的循环,大循环是【第一个乘数】的循环。每个【第一个乘数】中,都需要将所有的【第二个乘数】的可能性都算完。由于在 batch 中循环的写法太过于流氓,在不追求运行速度的情况下,我更愿意使用标签和跳转来实现循环。

具体写法如下:

:loop
::内容
goto loop

:bigloop
::内容
goto loop
::对没有写错,这里大循环结束后要进入小循环

而且,如你所见,这种写法也不依赖于循环之间的包含关系,比较灵活,随心所欲。

接着我们开始写小循环。

在小循环中,我们要实现以下操作:

  1. 用已经定义好的 t1 和 t2 来计算乘积,写入 tmp

  2. 将 tmp 作为加数累加到 num 中;

  3. 判断:若 t2==19,则跳转到大循环进行新的【第一个乘数】;否则计算同一个【第一个乘数】的下一个【第二个乘数】。

即:

:loop
::小循环
set /a tmp=%t1%*%t2% 
::计算乘积
set /a num=%num%+%tmp% 
::写入乘积
if /i %t2%==19 goto bigloop 
::若t2==19,跳转大循环(t1自增,t2原始值自增)
set /a t2=%t2%+1 
::否则只有t2自增
goto loop

在大循环里,我们需要实现:

  1. t1 自增;

  2. 将 t2 赋值为 t1 后的第一个互异数;

  3. 判断穷举是否完成。

即:

:bigloop
::大循环
set /a t1=%t1%+1
::t1自增
set /a t2=%t1%+1
::t1后第一个互异数赋值t2
if /i %t2%==20 if /i %t1%==19 goto result
::若穷举完成则输出结果
goto loop
::否则进入小循环

最后写 result 标签用于输出结果:

:result
echo 计算结果:%num%

整体框架出来以后,程序全文进行一些优化,加上题目和日志输出,加上结果暂留处理。完整代码如下:

@echo off
title 求知杯第6题
color f0
cls
echo 题目:将集合{1,2,……,19}中每两个互异的数作乘积,所有这种乘积的和为_.
echo 按下任意键开始计算
pause >nul
echo 题目:将集合{1,2,……,19}中每两个互异的数作乘积,所有这种乘积的和为_. >求知杯第6题.txt
::删除运行记录
set num=
set /a num=0
set t1=
set t2=
set /a t1=1
set tmp=
set /a t2=%t1%+1
::定义t1=1,t2=2
:loop
::小循环
set /a tmp=%t1%*%t2%
::计算乘积
set /a num=%num%+%tmp%
::写入乘积
set tmpecho=
set /a tmpecho=%num%-%tmp%
echo 计算过程:%tmpecho%+%t1%×%t2%=%num%
echo 计算过程:%tmpecho%+%t1%×%t2%=%num% >>求知杯第6题.txt
if /i %t2%==19 goto bigloop
::若t2==19,跳转大循环(t1自增,t2原始值自增)
set /a t2=%t2%+1
::否则只有t2自增
goto loop
::回到小循环
:bigloop
::大循环
set /a t1=%t1%+1
::t1自增
set /a t2=%t1%+1
::t1后第一个互异数赋值t2
if /i %t2%==20 if /i %t1%==19 goto result
::若穷举完成则输出结果
goto loop
::否则进入小循环
:result
echo 计算结果:%num%
echo 计算结果:%num% >>求知杯第6题.txt
echo 按下任意键退出程序
pause >nul


用 batch 解决小问题的评论 (共 条)

分享到微博请遵守国家法律