当前位置: 首页 > news >正文

第十四届蓝桥杯 2023 C/C++组 平方差

目录

题目:

题目描述:

题目链接:

思路:

核心思路:

第一种思路:

第二种思路:

坑点:

代码:

数学+找规律 O(n) 50分代码详解:

O(1)满分代码详解:

打表+找规律 O(1)代码详解:

补充平方差结论题目:

补充题目链接:

补充平方差结论代码详解:

河狸的数代码:

你不干?有的是帕鲁干!代码:


题目:

题目描述:

题目链接:

洛谷 P9231 [蓝桥杯 2023 省 A] 平方差

蓝桥云课 平方差

思路:

核心思路:

数学+找规律或打表+找规律

第一种思路:

第一种思路是用数论知识,用数学的方式推导出结论。如果之前有平方差的前置数学知识的话,这题很快就能解决,如果没有的话靠自己用数学知识也能推导出来,但是能不能想得到就是另一回事了

平方差结论:若a,b都是整数,则a^2-b^2一定是奇数或者4的倍数

a^2-b^2=(a+b)*(a-b),若a,b两个都是奇数,则a+b,a-b都是偶数,则(a+b)*(a-b)是4的倍数,因为偶数都有公共的质因子2,所以偶数*偶数一定是4的倍数; 若a,b一奇一偶,则a+b,a-b都是奇数,则(a+b)*(a-b)是奇数,因为奇数*奇数一定是奇数

再大白话地说:由题x=y^2-z^2,由平方差公式x=(y+z)*(y-z),y+z和y-z的奇偶性相同,5+3=8,5-3=2或5+4=9,5-4=1。所以x满足可以拆成两个奇偶性相同的数的乘积,如果x是奇数,可以拆成1乘以它本身。如果x是偶数,可以拆成两个偶数,所以应是4的倍数,拆成2和x/2。综上,答案是[l,r]区间的奇数和4的倍数的数的个数

第二种思路:

第二种思路是打表+找规律,这也是蓝桥杯常考的找规律的题的一种做法(后续我会总结蓝桥杯常见的找规律的题)。这里先简单提一嘴:找规律的题的特点:数据非常大,通常大于1e8,看上去非常吓人,肯定暴力跑不出来。但是一般有两个特性:1.周期性(结果在固定后重复)2.答案符合某种递推式。打表的意思就是先尝试暴力得到符合题目要求的前100、1000项来找规律。

坑点:

这题还有一个很阴的地方,即使你找到正确规律正常写也很容易踩坑。由题发现R最大为1e9,并且这题是编程题,也就是说正常一个for循环也会超时,只能拿50分。所以发现规律之后还得优化时间复杂度,把时间复杂度从O(n)优化到O(1)才能拿满分

代码:

数学+找规律 O(n) 50分代码详解:

#include<bits/stdc++.h> //这题主要考察数学+找规律,同时还有时间复杂度的问题 
using namespace std;    //这是我了解思路之后的第一个程序,时间复杂度O(n),只能拿50分,剩下50分超时 //这题只有把时间复杂度优化到O(1)才能拿满分
int l,r;
int cnt;int main()
{scanf("%d %d",&l,&r);for(int i=l;i<=r;i++) //遍历l到r的每一个整数,使用for循环,时间复杂度O(n) {if(i%2==1) //判断是奇数 {cnt++;}if(i%4==0) //判断是4的倍数 {cnt++;}}cout<<cnt<<endl;return 0;
}
//数学+找规律思路:
//由题x=y^2-z^2,由平方差公式x=(y+z)*(y-z),y+z和y-z的奇偶性相同,5+3=8,5-3=2或5+4=9,5-4=1 
//所以x满足可以拆成两个奇偶性相同的数的乘积
//如果x是奇数,可以拆成1乘以它本身
//如果x是偶数,可以拆成两个偶数,所以应是4的倍数,拆成2和x/2
//综上,答案是[l,r]区间的奇数和4的倍数的数的个数 

O(1)满分代码详解:

#include<bits/stdc++.h> //时间复杂度O(1),不会超时能拿全部分 
using namespace std;int l,r;int f_jishu(int x) //求从[0,x]区间奇数的个数 
{return (x+1)/2; //传入0->0 ,1->1 ,2->1 ,3->2 ,4->2 ~~101->51 
}int f_4(int x) //求[0,x]区间是4倍数的数的个数 
{return x/4; //显然传入3->0 ,4->1 ,7->1 ,8->2 ~~101->25 
}int main()
{scanf("%d %d",&l,&r);cout<<f_jishu(r)+f_4(r)-f_jishu(l-1)-f_4(l-1); //求[l,r]区间奇数和是4倍数的数的个数 return 0;
}

打表+找规律 O(1)代码详解:

#include<bits/stdc++.h>  //蓝桥杯常考的找规律的题,由题R最大为10^9,数据范围太大,暴力肯定不行 
using namespace std;  //平方差结论:若a,b都是整数,则a^2-b^2一定是奇数或者4的倍数
//a^2-b^2=(a+b)*(a-b),若a,b两个都是奇数,则a+b,a-b都是偶数,则(a+b)*(a-b)是4的倍数,因为偶数都有公共
//的质因子2,所以偶数*偶数一定是4的倍数; 若a,b一奇一偶,则a+b,a-b都是奇数,则(a+b)*(a-b)是奇数,因为
//奇数*奇数一定是奇数
//如果知道这个前置结论:题目就转换为L到R之间是奇数或者是4的倍数的数总和 int l,r;           //这题还有一个比较阴的地方就是,知道规律之后,用一次for还是会超时 //时间复杂度O(n),但是R最大为10^9,O(n)的话最大为10^9 >10^8,必须优化到O(1) 
int f_jishu(int x)
{return (x+1)/2;
}int f_4(int x)
{return x/4;
}int main()
{scanf("%d %d",&l,&r);cout<<f_jishu(r)+f_4(r)-f_jishu(l-1)-f_4(l-1);return 0;
}//如果不知道这个前置结论,做的时候也没推出结论,那别无他法的时候还是先暴力枚举100个看看有没有规律 
//int main()
//{
//	for(int i=1;i<=100;i++)  //暴力从1枚举到100找找看规律 
//	{
//		for(int j=0;j<=100;j++)  //i=k^2-j^2,由于搞不清到什么程度找不到j和k才算不满足要求 
//		{
//			for(int k=j+1;k<=100;k++) //所以先把i和k的终止条件先设大一点试试看 
//			{
//				if(i==k*k-j*j)
//				{
//					cout<<i<<' ';
//				}
//			}
//		}
//	}
//	return 0;
//}
//1 3 4 5 7 8 9 9 11 12 13 15 15 16 16 17 19 20 21 21 23 24 24 25 25 27 27 28 29 31 32 32 33 33 
//35 35 36 36 37 39 39 40 40 41 43 44 45 45 45 47 48 48 48 49 49 51 51 52 53 55 55 56 56 57 57 
//59 60 60 61 63 63 63 64 64 64 65 65 67 68 69 69 71 72 72 72 73 75 75 75 76 77 77 79 80 80 80 
//81 81 81 83 84 84 85 85 87 87 88 88 89 91 91 92 93 93 95 95 96 96 96 96 97 99 99 99 100 100
//输出数据发现有的数会重复输出几次,是因为j,k设置的终止条件满足能找到多种组合来平方差得到i
//但是毕竟是没有其他思路办法的无奈之举,所以把重复的数删一下再找找有没有规律 
//1 3 4 5 7 8 9 11 12 13 15 16 17 19 20 21 23 24 25 27 28 29 31 32 33 35 36 37 39 40 41 43 44 45 
//47 48 49 51 52 53 55 56 57 59 60 61 63 64 65 67 68 69 71 72 73 75 76 77 79 80 81 83 84 85 87 88
//89 91 92 93 95 96 97 99 100
//这些就是删去重复的满足题目要求的解了,通过这些数勉强能看出奇数和4的倍数能满足要求,但是有点抽象

补充平方差结论题目:

补充题目链接:

蓝桥云课 河狸的数(平方差结论)

蓝桥云课 你不干?有的是帕鲁干!(平方差结论拓展)

补充平方差结论代码详解:

河狸的数代码:

#include<bits/stdc++.h>
using namespace std;const int N=1e5+10;  //多开一点,防止数组越界 int n;
long long a[N];      //由题整数最大为10^18,会爆int,一定要开long long int main()
{cin>>n;for(int i=0;i<n;i++){scanf("%lld",&a[i]);if(a[i]%4==0||a[i]%2==1)  //平方差结论 {printf("Yes ");}else{printf("No ");}}return 0;
}

你不干?有的是帕鲁干!代码:

#include<bits/stdc++.h> //这题是平方差结论的拓展,由题要求x可以被表达成两个连续正奇数的平方之差 
using namespace std;    //两个连续正奇数:2*k-1 2*k+1(从1开始,所以k=1,2,3...)
//由平方差公式:(2*k+1)^2-(2*k-1)^2=(2*k+1+2*k-1)*(2*k+1-2*k+1)=8*k  k=1,2,3...
//所以如果x能被表达为两个连续正奇数的平方之差,则x是8的倍数,注意由题x从0开始,但是x不能为0,因为k从
//1开始,即最小满足能被表达成两个连续正奇数的平方之差的数是8,所以判断条件是x!=0&&x%8==0,输出Yes
//题目还要求从小到大输出这两个连续正奇数,即先求k=x/8,a=2*k-1,b=2*k+1,输出a b即可 long long x;  //由题输入的非负整数x最大为10^18,会爆int,要开long long 
int n;int main()
{cin>>n;while(n--){scanf("%lld",&x);if(x!=0&&x%8==0)   //由结论判断x是否能被表达成两个连续正奇数的平方之差 {printf("Yes\n");long long k=x/8;   //注意x最大为10^18,x要开long long,那么k,a,b都要开long long long long a=2*k-1; //因为k,a,b都是很小的运算,如果x爆int,则k,a,b后续运算也会爆int long long b=2*k+1;printf("%lld %lld\n",a,b);}else{printf("No\n");}}return 0;
}

相关文章:

  • 设计模式 建造者模式
  • Pycharm(九)函数的闭包、装饰器
  • compat-openssl10和libnsl下载安装
  • Java高效合并Excel报表实战:GcExcel让数据处理更简单
  • 靠华为脱胎换骨,但赛力斯仍需要Plan B
  • MySQL访问权限授权问题
  • 二分查找、分块查找、冒泡排序、选择排序、插入排序、快速排序
  • SPL 量化 序言
  • 【FFmpeg从入门到精通】第四章-FFmpeg转码
  • 性能比拼: Nginx vs Caddy
  • 乾元通渠道商中标舟山市自然灾害应急能力提升工程基层防灾项目
  • VTK知识学习(53)- 交互与Widget(四)
  • Kubernetes 创建 Jenkins 实现 CICD 配置指南
  • 5.2.1 CallerMemberName的使用
  • 02-HTML结构
  • 在线查看【免费】vsd, vsdx/wmf, emf /psd, eps/pdf ,ofd, rtf/xmind/bpmn/eml/epub文件格式网
  • 驱动开发硬核特训 · Day 16:字符设备驱动模型与实战注册流程
  • 基于STC89C52RC和8X8点阵屏、独立按键的匹配消除类小游戏
  • unity3d实现物体闪烁
  • Discuz论坛网站忘记管理员密码进不去管理中心怎么办?怎么改管理员密码?
  • 规模再创新高,超百款新车首发!上海车展明日开幕
  • 庆祝中国印尼建交75周年招待会暨万隆会议70周年纪念活动在京举行
  • 夜读丨一位医生0点后的朋友圈
  • 中小企业收款难何解?快速认定企业身份并理顺付款责任链条
  • 著名世界语教育家、翻译家魏以达逝世
  • 延安市委副书记马月逢已任榆林市委副书记、市政府党组书记