1. 题目

T1 魔力石

题目描述

题目描述

小明有一排魔力石,魔力石是一种蕴含魔力的石头,运用得当就能从中提取魔力。

魔力可以通过震荡的方式激发出来,这是提取魔力的唯一方法,而最好的震荡方式就是聚拢同一频率的魔力石让他们共振,同一频率的魔力石越多,激发过程越顺利。

每一个魔力石都有他们自己的频率 \(A_i\) ,而小明可以使用特别的方法对魔力石的频率进行微调,让它的频率暂时 \(+1\) 或者 \(-1\),当然也可以不变。

请问小明现在最多可以得到多少个频率相同的魔力石。

输入格式

输入第一行,一个整数 \(N\) ,表示魔力石的个数。

输入第二行包含 \(N\) 个整数 \(A_i\),表示每个魔力石的频率。

输出格式

输出共 \(1\) 行,表示多可以得到多少个频率相同的魔力石。

样例输入

8
3 1 4 1 5 9 2 6

样例输出

4

数据范围

  • 对于 \(50\%\) 的数据,\(1≤N≤1000\)
  • 对于 \(100\%\) 的数据,\(1≤N≤10^6\)\(1≤A_i≤10^6\)

Sol

\(O(n^2)\) 暴力可以获得 50pts .

扫一遍,每次二分看看 \(A_i-1\)\(A_i\)\(A_i+1\) 的数量,这样时间复杂度是 \(O(n\log n)\) 的,100pts .

输入的时候把 \(A_i\) 丢到桶里,然后扫一遍,直接 \(O(1)\) 统计 \(A_i-1\)\(A_i\)\(A_i+1\) 的数量,这样时间复杂度是 \(O(n)\) 的,100pts .

T2 和

题目描述

题目描述

小明喜欢在上课的时候玩速算游戏,今天他玩的速算游戏如下:

现在纸上写下一个长为 \(N\) 的正整数,然后开始在数码之间添加 \(+\),添加的数量不限制(也可以不添加),只有以下一条规则

  • 保证添加完 \(+\) 后,它是一个合法的,可以计算的算式(我们认为完全不添加 \(+\) 时也算一个算式,此时它仍然是单独的一个数)

小明的想法是,他先得到所有合法的 \(+\) 算式,将这些算式依次计算后(单独的一个数依旧算作它本身),再把他们的和加在一起,得到 \(ans\)

他想邀请你来一起玩这个游戏。

输入格式
输入共 \(1\) 行,小明写在纸上的整数。

输出格式

输出共 \(1\) 行,即答案。

样例输入

125

样例输出

176

数据范围

  • 对于 \(30\%\) 的数据,\(2≤N\text{(数字位数)}≤2\)
  • 对于 \(50\%\) 的数据,\(2≤N≤5\)
  • 对于 \(100\%\) 的数据,\(2≤N≤16\)。(你可以认为答案不会超过 long long

Sol

数据范围才 \(16\),写个 \(O(2^n)\) 的枚举子集即可通过。

string s;
cin>>s;
ll ans=0; int len=s.length();
for (int bit=1;bit<(1<<s-1);bit++)
{
	ll tmp=0,now=0;
	for (int i=0;i<len-1;i++)
	{
		tmp=tmp*10+s[i]-'0';
		if (bit&now) ans+=tmp,tmp=0;
		now<<=1;
	} ans+=tmp*10+s[len-1]-'0';
}
printf("%lld",ans);

T3 数对

题目描述

题目描述
小明现在有 \(2N\) 个数字,不妨记为 \(a_1,a_2,\cdots,a_{2N}\),对于每个 \(a_i\),都满足 \(0≤ai<P\)

现在小明打算将这些数字分成 \(N\) 组,每组 \(2\) 个数字,假设某一组为 \((x,y)\),那么这一组的得分为 \((x+y)\bmod P\)

由于一共 \(N\) 组,故令所有组得分的最大值就是整体的得分,不妨记为 \(Score\)

分组的方式有很多种,每种分组方式对应了一个 \(Score\) 值,小明现在想知道 \(Score\) 的最小值,可以帮帮他么?

输入格式

输入第一行,两个整数 \(N,P\),含义如题目描述。

输入第二行包含 \(2N\) 个数字 \(a_i\) ,含义如题目描述。

输出格式

输出共 \(1\) 行,表示 \(Score\) 可能的最小值。

样例输入

3 10
0 2 3 4 5 9

样例输出

5

数据范围

  • 对于 \(30\%\) 的数据,\(1≤N≤10\)
  • 对于 \(50\%\) 的数据,\(1≤N≤2000\)
  • 对于 \(100\%\) 的数据,\(1≤N≤10^5\)\(1≤P≤10^9\)

Sol

最大值最小,直接二分。
check 的时候用二分图匹配,时间复杂度 \(O(n^2\log n)\),50pts .

这题其实是个贪心题

数应该分为两类,一类相加会超过 \(P\) ,一类相加不会超过 \(P\) .

我们将从小到大的数分成两部分

左半部分和右半部分,两部分的策略都相同:即最小的和最大的相加,次小的和次大的相加。特别要指出的是:对于右半部分,他们相加一定大于 \(P\)

利用二分找出这个分界点,然后两边相加计算答案即可,100pts .

T4 海豹王国

题目描述

题目描述

小明来到了海豹王国游玩,海豹王国一共有 \(N\) 座城市,每座城市都有自己独特风格的主题乐园,并且每个乐园都有独特的签章,来乐园游玩的游客都可以获得。

除此之外,如果你能够从一座城市出发,恰好经过每个城市一遍,并最后回到起点(此时除了起点所有城市被访问了一遍,起点被访问了两遍),那么就可以获得一个更稀有的“全收集限量签章”。实不相瞒,收集所有的签章便是小明的目的(就是走一个哈密尔顿回路)。海豹王国的交通异常发达,所以任意两个城市之间都有直达道路

现在有一个好消息和一个坏消息,好消息是所有城市的乐园都免费,坏消息是从一座城市到另一座城市要缴纳费用

缴费的方式比较特殊,每个城市 \(i\) 有两个费用,出城费 \(A_i\),和入城费 \(B_i\),那么从城市 \(i\) 到城市 \(j\) 的交通费用为 \(\min(A_i,B_j)\) .

求小明达成目的的最小花费。

输入格式

输入第一行,一个整数 \(N\) ,表示城市个数。

接下来 \(N\) 行,每行包含 \(2\) 个数字 \(A_i,B_i\)

输出格式

输出共 \(1\) 行,表示最小需要多少路费。

样例输入

3
1 5
4 2
6 3

样例输出

7

样例解释

\(1 \to 3 \to 2\to1\) .

数据范围

  • 对于 \(50\%\) 的数据,\(2≤N≤10\)
  • 对于 \(100\%\) 的数据,\(2≤N≤10^5\)\(1≤A_i,B_i≤10^9\)

Sol

又 是 贪 心 题

因为每个点只能走一次,所以每个 \(A_i,B_i\) 也只能用一次。

那么一个合理的贪心思路:取 \(\{A_i\}\)\(\{B_i\}\) 中的前 \(N\) 个,判断这种情况下是否能形成哈密尔顿回路,如果可以则直接输出,不可以则强制枚举一个起点和终点,更新答案。

考场策略

反面教材(不适用于神仙):

  1. 这道题目的算法我似乎看见过。。嗯。。这肯定就是标算!怎么写来着我琢磨一下现场推推看(完全忽略了那个算法几乎没怎么写过也差不多忘的一干二净)
  2. 哇!只剩 \(\rm 30\;min\) 了!没事没事,最后一题能写完的,还有最后的 \(40\) / \(70\) / AK 我一定要拿到!!!(嗯。。。完全没有给自己留检查的时间)
  3. 简单题都写了。。难题都不会。。我还是睡觉吧。。打会扫雷(windows 选手)或者贪吃蛇(linux 选手)?
  4. 嗯!题目给的大数据都过了!那这题基本稳了!对拍好麻烦啊,我还是去写下一题吧。爽!贼快!
  5. 典型5 : 哦!这题不是很(我)简(做)单(过)嘛,秒出解!(写完题跑样例——嗯?发生了什么?)

安排时间:

  1. 先分配每道题的时间
  2. 时间分配应该考虑到 .
    • 看题:题目名(?),时空限制,输入输出格式。
    • 反思:重新看一遍题目,对样例输入输出用你的算法做一遍诠释,思考自己的算法是否有漏洞和反例,思考极限情况,造数据。(hacker 现状)
    • 检查:检查分为两步,题目做完后的检查,考试临近时的检查
      1. 题目做完后
        • 空间是否足够?(RE 警告)
        • 测极限数据看看会不会 tle 或溢出(检查取模和公式)
        • 是否删了调试?(((
      2. 考试临近时:
        • 文件名?
        • 看看数组和常数(long long MAX=(1<<61)-1,此时 1<<61int 类型的,会溢出,正确写法:long long MAX=(1ll<<61)-1int pi=acos(-1),正确写法:double pi=acos(-1.0))是否脑残?
        • 是否删了调试?(梅 开 二 度)
        • 重新编译一下?样例是否还能过?(没 保 存 产 生 的 事 故)

时间分配:

  1. 先看题,分配时间
  2. 开始细读每一题,想题,反思,写题,造数据,调试
  3. 检查,下一题
  4. 如果你有空,并且已经写完所有代码了(或者写不出来了):造数据对拍;如果考试要结束了直接第 \(5\)
  5. 进行考试结束时的检查 把你下定决心不再改的题目的代码检查一遍,保存好
  6. 好了,现在可以继续你想拼一把的题了

细节处理:

  1. 一定要熟练使用终端
  2. 在复杂公式旁边标注,方便调试(我公式肯定没错!要是错了我当场把这个电脑屏幕吃掉!啊这公式没取模)
  3. 及时关掉不改的代码、已经写完的题目,免得开错
  4. 变量名和函数名尽量有意义,但不要太像系统函数和保留字(解决方案:my+functionname;驼峰式名字;不 using namespace std;;开个 namespace(不建议))
  5. 任何修改算法和大批代码的行为都要备份原代码(诶这题好像不是最小生成树,好像是二分?删了改改 \(\cdots\) 诶这题好像不是二分,好像是最小生成树?删了改改 \(\cdots\) 诶这题好像不是最小生成树,好像是二分?啊考试结束了交个最小生成树上去罢,喜提 0pts)

算法选择:

  • 你已经基本不会错的算法 \(>>\) 你没把握的算法
  • 一定能写对的算法 \(>>\) 可能可以拿高分的算法
  • 请绝对不要盲目尝试你只是听说连些都没写过或者你已经忘了的算法(我记得拓扑排序思想,我一定能当场写对!(0pts))
  • 不要低估暴力算法,尤其是可能是 dp 的题目(啊写个暴力罢,哦这好像可以剪枝,哦这好像可以记忆化,哦这好像就是 dp,100pts)
  • 不要低估出题人的智商,去写一些只能骗自己的骗分(有尊严地写题)

上面提到的东西,并不是一朝一夕能养成的,或者是你在考试前一天拿出来读一遍就能做到的——你可能走上考场依旧是手忙脚乱。

如何在考场上优雅地发挥?——想要无论何时都保持优雅,你得从平时就开始要求自己,比如

代码风格,代码风格,代码风格!重要的事情说三遍!

inline void ________(){
    ______[1]=1;
    for(register int _________=2;_________<=10000000;++_________){
        if(!______[_________]) _______[++_______[0]]=_________;
        for(register int __________=1;__________<=_______[0]&&_________*_______[__________]<=10000000;++__________){
            ______[_________*_______[__________]]=1,_______[_________*_______[__________]]=1;
            if(_________%_______[__________]==0) break;
        }
    }
}

然后同样重要的 : 写题速度,查错能力,对数据范围和特殊情况的敏感程度

典 型 反 例:

  • 拿到题目我先写点什么。。。嗯。。。大概会用到所以我先写着(尤其是在焦虑的时候)
  • 一旦程序出错(CE、RE、UKE)先打开调试 / 输出一些什么东西,一旦答案错了(WA)先调数据。
    你应该对你的代码在哪一块可能会出错有一个感觉
    你改正不了第一点,你就别想做到这一点
  • 题目写完啦!样例过啦!嗯老夫先去爆一爆 OJ 庆祝庆祝 / 圣斗士不会败给同样的题目两次,所以这题我不做。
    估计你这辈子都别想提升你一次 AC 的几率了。

如果出现如下症状:

  • 对学习新的骚(黑)操(科)作(技)和新算法有着强烈的兴趣,但是你做题的时间很少,你的高级算法只停留在会做裸题上。
  • 你总是把简单的题目搞复杂,容易把题目往难的方向想
  • 每次考试你都成功地在一些相同水平的人不会丢分的地方丢了分

恭喜恭喜啊,同学你眼高手低啊,说明基础根本不扎实嘛

对症下药:

  • 调试能力差——改善代码风格,保证写代码头脑清醒
  • 代码风格差——多写模拟题,多看别人的代码,培养意识
  • 准确率低、考虑不周全——慎重提交,拿个本子(或者 blog)总结一下自己经常考虑不到的问题和逗逼错误和做题心得
  • 多写暴力题——你至少要有能极快地写出对拍程序的水平
  • 多比赛,多模拟考——培养考试策略和感觉以及骗 分 能 力

然后你就可以优雅地上考场了

做历年题:为什么要做历年题呢?反正他们都不可能再考一遍了,三个理由:

  1. 你能看出 NOIp 大概会考什么类型的题目,而你需要注意些什么
  2. 历年的题目质量有保障,是一等一的好题、经典题,相当于教科书上的例题一样
  3. 历年题的安排和分数分布及其科学,是你能用来锻炼骗分技巧的为数不多的题目

e.g. 对称二叉树暴力上加个剪枝直接 AC