Peter算法小课堂—枚举优化

2024-02-09 21:44

本文主要是介绍Peter算法小课堂—枚举优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

哈哈哈,新年快乐!这一次Peter将要给大家讲一讲轻松、摆烂的算法—枚举!咋就是说呀,枚举这个玩意我语法就会了。但大家想想,咱们CSP考试时(除了没过初赛的)只给1秒,大家想想,这出题老师得有多抠啊。大伙们信不信,就这种easy的题,都配出进普及组,不管大家信不信,例题给我搬上来

[NOIP2016 普及组] 回文日期

题目描述

在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。

牛牛习惯用 8 位数字表示一个日期,其中,前 4 位代表年份,接下来 2 位代表月份,最后 2 位代表日期。显然:一个日期只有一种表示方法,而两个不同的日期的表 示方法不会相同。

牛牛认为,一个日期是回文的,当且仅当表示这个日期的 8 位数字是回文的。现在,牛牛想知道:在他指定的两个日期之间包含这两个日期本身),有多少个真实存在的日期是回文的。

一个 8 位数字是回文的,当且仅当对于所有的 i(1≤i≤8)从左向右数的第 i 个数字和第 9−i 个数字(即从右向左数的第 i 个数字)是相同的。

例如:

  • 对于 2016 年 11 月 19 日,用 88 位数字 20161119 表示,它不是回文的。
  • 对于 2010 年 1 月 2 日,用 88 位数字 20100102 表示,它是回文的。
  • 对于 2010 年 10 月 2 日,用 88 位数字 20101002 表示,它不是回文的。

每一年中都有 12 个月份:

其中,1,3,5,7,8,10,12 月每个月有 31 天;4,6,9,11 月每个月有 30 天;而对于 2 月,闰年时有 29 天,平年时有 28 天。

一个年份是闰年当且仅当它满足下列两种情况其中的一种:

  1. 这个年份是 4 的整数倍,但不是 100 的整数倍;
  2. 这个年份是 400 的整数倍。

例如:

  • 以下几个年份都是闰年:2000,2012,2016。
  • 以下几个年份是平年:1900,2011,2014。

 大家看道题给大家做个不用脑子的选择吧

当然,选B的人一定有那么一点点的**。这个选择题应该选 B D。

啊这,请大家 写一写代码 注意:看到这题千万别崩溃

先学两个语法吧,啥?语法?我学过了啊?

语法1

#include <bits/stdc++.h>
using namespace std;
int main(){string year="2019";reverse(year.begin(),year.end());cout<<year<<endl;int x[3]={7,8,9};reverse(x,x+3);cout<<x[0]<<x[1]<<x[2]<<endl;return 0;
}

仔细观察此代码,有什么难以理解的地方。这叫“序列反转”。大家自己玩玩试试。当然,CSP时尽量多使用一些系统封装好的的函数,以免这个傻了吧唧调试几次没成功的,WA满天飞。

语法2

#include <bits/stdc++.h>
using namespace std;
void I2S(int x,string&str){stringstream ss;if(x<=9) ss<<0;ss<<x;ss>>str; 
}
int main(){string s;I2S(1,s);cout<<s<<endl;I2S(12,s);cout<<s<<endl;return 0;
}

这个属于int转string。来,看看&是什么,是引用传递!传递什么,传递地址啊,这可以让这个庞大的字符串变成轻量级的地址。

开始写代码八!

过亿会儿公布答案。

噔噔噔噔,公布答案啦

#include <bits/stdc++.h>
using namespace std;
void I2S(int x,string&str){stringstream ss;if(x<=9) ss>>0;ss<<x;s>>str; 
}
int nDays[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int main(){string date1,date2;cin>>date1>>date2;int ans=0;for(int m=1;m<=12;m++){string month;I2S(m,month);for(int d=1;d<=nDays[m];d++){string day;I2S(d,day);string md=month+day;string year=md;reverse(year.begin(),year.end());string date=year+md;if(date>date1&&date<=date2) ans++;}}cout<<ans<<endl;return 0;
}

 [NOIP2008 提高组] 火柴棒等式

题目描述

给你 n 根火柴棍,你可以拼出多少个形如 A+B=C 的等式?等式中的 A、B、C 是用火柴棍拼出的整数(若该数非零,则最高位不能是 0)。用火柴棍拼数字 0∼9 的拼法如图所示:

注意:

  1. 加号与等号各自需要两根火柴棍;
  2. 如果 A≠B,则 A+B=C 与 B+A=C 视为不同的等式(A,B,C≥0);
  3. n 根火柴棍必须全部用上。

提高组2008年第2题?考枚举?不可思议啊?那么学完例一过后,大家是不是有了亿点思路了呢?所以……请大家写写代码八!!!

预处理1

match[]数组表示单个数字i需要用几个火柴,i=0,1,2,3,4,5,6,7,8,9

所以请大家计算一下match[]数组的值。

答案是:

当然,摆的数不一定是个位数,还有可能是两位数、三位数……。于是,这个预处理还不够。

预处理2

然后,请大家打开DEV-C++,写一下matches()函数,它的功能是“给定一个整数x,x=0~999,求组成x要多少火柴”。过亿会儿公布答案。

void matches(){for(int x=0;x<N;x++){int y=x;do{cnt[x]+=match[y%10];y/=10;}while(y);}
}

注意:x从0开始,要用do……while

枚举

OK!那么现在,大家想想怎么枚举的呢?我给大家一个原稿,大家试着优化一下。优化方面:1.枚举对象 2.枚举范围 3.枚举顺序

int ans=0;
for(int A=0;A<=1000;++A){for(int B=0;B<=1000;++B){for(int C=0;C<=1000;++C){if(A+B==C&&cnt[A]+cnt[B]+cnt[C]+4==n){ans++;}}}
}
cout<<ans<<endl;

代码写完网上一交,唉,还真AC(All Clear)了,挺神奇的哈,这个某谷

但你想想,但凡出题老师吝啬一点,我们这代码不管什么数据,都是0分,俗称爆0。为什么呢?因为你怎么变这个数据,代码都是运行10^9次,也就是1亿次。

后面我们分两种方法详细的给大家讲讲如何优化

打表

咱们发现那,n<=24,一共就只有24种情况,咱不妨……打个表试试?所以可以提前打表,最终提交表格。有人问到,我们这表格咋填嘞。这个本地运行时间充裕,保证正确。这个办法大家尝试尝试。

减少枚举对象

对象?

啊这……其实,我们只要枚举A,B,算出C,再判断即可,所以……满满分代码来啦。

#include <bits/stdc++.h>
using namespace std;
int match[10]={6,2,5,5,4,5,6,3,7,6};
const int N=999;
int n,cnt[N];
void matches(){for(int x=0;x<N;x++){int y=x;do{cnt[x]+=match[y%10];y/=10;}while(y);}
}
int main(){cin>>n;matches();int ans=0;for(int A=0;A<=1000;A++){for(int B=0;B<=1000;B++){int C=A+B;if(cnt[A]+cnt[B]+cnt[C]+4==n){ans++;}}}cout<<ans<<endl;return 0;
}

来,又又又完成一题,再来一题。

啊啊啊啊

股神

题目描述

作为股神,你的神力是能看到未来n天里每天股票的盈利或者亏损,第i天盈利x[i]元,当然如果x[i]是负数,代表亏损。一次投资可以发生在任意连续天。为了不让人发现你的神力,你必须挑选两段不重叠也不连续的投资,来掩人耳目。请计算你最多盈利多少?

这叫做“两段最大子段和问题”。考虑两个算法,①枚举4个端点 ②枚举分割点

第1中算法时间复杂度O(N^4),大家嚼的可能吗?可能。那么,我们要左右预计算了。这样吧,这道题就当作小练习,码量不多,就20多行,不要抄答案哦👍

发一个表情包分割答案

#include <bits/stdc++.h>
using namespace std;
const int N=200009;
int n,LR[N],L[N],R[N],x[N],f[N],g[N];
int main(){cin>>n;for(int i=1;i<=n;i++) cin>>x[i];for(int i=1;i<=n;i++)f[i]=max(f[i-1],0)+x[i];L[1]=f[1];//L[]表示在1到i号的最大子段和,f[]表示以i号结尾的最大子段和 for(int i=2;i<=n;i++)L[i]=max(L[i-1],f[i]);for(int i=n;i>=1;i--)g[i]=max(g[i+1],0)+x[i];R[n]=g[n];for(int i=n-1;i>=1;i--)R[i]=max(R[i+1],g[i]);for(int i=2;i<=n-1;i++)LR[i]=L[i-1]+R[i+1];cout<<*max_element(LR+2,LR+n)<<endl;return 0;
}

这题需要亿点动态规划的知识,不会的翻我主页就好了。

好了,到这里就结束了,给大家送句祝福:新年伊始,万象更新。愿所念之人,平安喜乐;愿所想之事,顺心如意。诶,大家看春晚了不?

这篇关于Peter算法小课堂—枚举优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/695356

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份