引言
备战蓝桥杯的你是否曾被找规律题“卡脖子”?这类题目看似玄学,实则暗藏套路!
它们数据量爆炸(轻松超1e8)!它们让我们暴力枚举直接超时!
别慌!使用暴力打表前100项 + 观察周期 / 递推规律,才是破解这类题的终极钥匙!
本文手把手带你剖析找规律题的三大特征(高数据量、周期性、递推性),并通过四道经典例题实战演示如何用代码快速生成关键数据,从乱序数字中一眼锁定隐藏的数学规律,轻松避开溢出陷阱。文末附文章例题暴力打表代码,助你赛场上一招制胜,省时又省力!速速收藏,拒绝无效刷题!🚀
文章例题参考:
up主:溶金落梧桐
b站视频:蓝桥杯常考的找规律题,学会套路轻松拿捏
特点解析
找规律题的特点:
- 数据量非常大(通常大于1e8),很容易溢出,不可能用代码暴力求出;
- 有周期性;
- 答案有递推关系;
通解:暴力输出前100项后找!规!律!
下面带着大家来看看例题:
一、报数游戏
https://www.lanqiao.cn/problems/19698/learning
因为202420242024是很大的数字,所以直接考虑找规律;
我们按照题目中的暗示(给出前10个报出的数字),所以我们每10个数字换一次行,可以得到如下的输出:
观察可得:每次第10个数字,都是120的倍数,也可以说是12的倍数,更具体地来说:
- 第10个数字:12 * 10 =120;
- 第20个数字:12 * 20 =240;
- 第30个数字:12 * 30 =360;
- 第40个数字:12 * 40 =480;
到这里规律已经很明显了。所以,202420242020肯定也是12的倍数,按照上述规律可求得:
- 第202420242020个数字:12 * 202420242020;
下面只需求出相邻组中,0到4所产生的变化。
很显然,120 -> 168(+48);240 -> 288(+48);360 -> 408(+48)......
所以我们只需加上48即可得到答案,最终计算式为:
- 12 * 202420242020 + 48 = 2,429,042,904,288;
提交,结果正确。
二、阶乘求和
https://www.lanqiao.cn/problems/3500/learning
我们首先看到202320232023!是一个很大的数字,故考虑直接找规律!
概念“阶乘尾0”:n!随着n的值变大,尾部的0会越来越多;
同样我们输出前100项数据的后9位,直接寻找规律:
答案即为:420940313
提交,结果正确。
我们也可以尝试着取更多位数来验证阶乘尾0的概念,若mod=1e15:
从上图也可以看到末位是逐渐稳定的!
警告:
时刻注意上限:const long mod = 1e9; 已是最大,超过则需换成更大的数据类型,如long long;
三、数字诗意
https://www.lanqiao.cn/problems/19714/learning
看到下面红圈内容,1e16的数据范围考虑是否有规律可找!
对于这个题目,我们考虑找到不蕴含诗意数字的特点,故输出前100、1000个数字中的情况:

很明显,我们发现都是2的倍数(加上1、2两个不优雅的数字),故我们可以猜测:若是2的倍数(0到n倍),则该数字不优雅!
所以题目变成了:从输入的数字中,去除2的倍数即可!
下一步则是剔除 2 的幂次方——up主没有往下讲这个,而是讲其他题去了,我接着进行了补全。由于题目的数据限制,这个地方比我想象中的要困难!!!
总是只能拿到30%的分,而对于最大的数据(1e16),我尝试开最大的__int128类型,但是仍然产生了溢出,导致结果不正确,这很令人头疼!
查阅题解和gpt后,我使用“ a & (a - 1) == 0 ”来判断 a
是否是 2 的幂次方——据悉,这是一个“经典的技巧”......好吧,学习了。
四、平方差
https://www.lanqiao.cn/problems/3502/learning
同理:考虑到下面的平方和数值大小,我们采用找规律来尝试解题:
理解题意:寻找平方差得到结果的特征!
对于题目中的公式进行拆分:x = y^2 - z^2 = (y-z)(y+z);
此时我们对于上述y、z两数的奇偶性进行讨论:
- 当 y、z 一奇一偶,得奇数相乘,结果为奇数;
- 当 y、z 同奇 / 同偶数,得到偶数相乘,结果为偶数,且能被4整除;
故即查找 [L, R] 间有多少个为奇数或者能被4整除的数!
又是经典结论......而且目前只能看出:
平方差的计算结果有这个性质;但是此处并未证明如果符合这个性质,一定是平方差的计算结果
所以先标记一下,应该是可证的。
但是!
又遇到问题了。正常的计算方法会由于溢出而只能通过90%的数据;
所以借鉴了他人的题解,使用 “ ans = get_sum(r)-get_sum(l-1); ”成功拿到100%;
其中 get_sum() 函数如下:
//获取[1...x]中 4的倍数 和 奇数的个数,前者下取整,后者上取整
ll get_sum(ll x){
return x / 4 + (x + 1) / 2;
}
思路(来自平方差-louvre的代码):
- x/2上取整可以获得[1,x]奇数个数: ⌈9 / 2⌉ = 5(1,3,5,7,9为[1,x]的奇数)
- x/4下取整可以获得[1,x]4的倍数的个数⌊5 / 4⌋ = 1(只有4一个为4的倍数)
再分别获取[1...r]和[1...l-1]区间内两种数字个数做差减去交集,即可得到答案。
代码
1、报数游戏
#include <bits/stdc++.h>
using namespace std;
int cnt=0;
int main()
{
for(int i=1;cnt<100;i++){
if(i%20==0 || i%24==0){
cnt++;
cout<<i<<' ';
if(cnt%10==0) cout<<endl;
}
}
return 0;
}
2、阶乘求和
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const long long mod = 1e9;
int main()
{
ll sum=0; // 结果
ll fac=1; // 阶乘(一直往上乘)
for(int i=1;i<=100;i++){
fac=(fac*i)%mod;
sum=(sum+fac)%mod;
cout<<sum<<endl;
}
return 0;
}
3、数字诗意
part1:不蕴含诗意数字的特点
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// check a
int check(int a){
for(int j=1;j<a;j++){
int sum=0;
for(int k=j;k<a;k++){
sum+=k;
if(sum==a) return 1;
}
}
return 0;
}
int main()
{
// 尝试输出3~100中不优雅的数字
for(int i=3;i<=1000;i++){
if(!check(i)) cout<<i<<endl;
}
return 0;
}
part2:剔除( 技巧:(a&(a-1))==0来剔除 2 的幂次方)
#include <iostream>
using namespace std;
typedef long long ll;
int main()
{
ll n,ans=0,a;
cin>>n;
for(ll i=0;i<n;i++){
cin>>a;
if((a&(a-1))==0) ans++; // 判断2^n
}
cout<<ans;
return 0;
}
4、平方差
#include <iostream>
typedef long long ll;
using namespace std;
//获取[1...x]中 4的倍数 和 奇数的个数,前者下取整,后者上取整
ll get_sum(ll x){
return x / 4 + (x + 1) / 2;
}
int main()
{
ll l,r;
ll ans=0;
cin>>l>>r;
// for(ll i=l;i<=r;i++){ // 90%
// if(i%4==0 || i%2==1) ans++;
// }
ans = get_sum(r)-get_sum(l-1);
cout<<ans;
return 0;
}