1.分队问题
描述
给定n 个选手,将他们分成若干只队伍。其中第i 个选手要求自己所属的队
伍的人数大等于a[i]人。
在满足所有选手的要求的前提下,最大化队伍的总数。
注:每个选手属于且仅属于一支队伍。
输入格式
第一行一个整数 n,表示人数。 以下 n 行,每行一个整数表示 a[i]。
输出格式
输出队伍总数的最大值。数据保证有解。
数据范围
对于 20%的数据,n <= 10 对于 40%的数据,n <= 1000 对于 60%的数据,n <= 10000 对于 100%的数据,1 <= n <= 10^6
考试时想的是贪心,没想dp,没有读入优化。。。
正解:
将选手的
从小到大排个序,然后dp:
状态:
表示前i名选手能构成的最多队伍数。
方程:
其中
然后用
提前计算前j个f的最大值即可。
时间复杂度:
2.子矩阵
题目描述
小 A 有一个 N×M 的矩阵,矩阵中 1~N*M 这(N*M)个整数均出现过一次。 现在小 A 在这个矩阵内选择一个子矩阵,其权值等于这个子矩阵中的所有数的最 小值。小 A 想知道,如果他选择的子矩阵的权值为 i(1<=i<=N×M),那么他选择 的子矩阵可能有多少种?小 A 希望知道所有可能的 i 值对应的结果,但是这些结 果太多了,他算不了,因此他向你求助。
输入格式
第一行,两个整数 N,M。 接下来的 N 行,每行 M 个整数,表示矩阵中的元素。
输出格式
N×M 行,每行一个整数,其中第 i 行的整数表示如果小 A 选择的子矩阵权 值为 i,他选择的子矩阵的种类数。
数据范围
对于 30%的数据,1<=N,M<=50; 对于全部的数据,1<=N,M<=300。
考试时想的 暴力处理拿30分。
正解:
先用
处理出每个以i为矩阵上边,以j为下边,第k列的小子矩阵的最小值。
然后使用单调栈,将对于每个元素可以延伸的左右界求出即可。总共
显然对于一个子矩阵的最小值,它会影响左边,右边比它大的元素延伸矩阵,就可以用单调栈了。
3.数字对
题目描述
对于一个数字对(a,b),我们可以通过一次操作将其变为新数字对(a+b,b)或(a, a+b)。 给定一正整数 n,问最少需要多少次操作可将数字对(1,1)变为一个数字对, 该数字对至少有一个数字为 n。
输入格式
第一行一个正整数 n
输出格式
一个整数表示答案。
数据范围
对于 30%的数据, 1<=n<=1000 对于 60%的数据, 1<=n<=20000 对于 100%的数据,1<=n<=10^6
考试时打表后迭代加深然后卡时才苟且通过。。。。太弱了。
正解:
显然从
递推到n肯定不可行,就考虑从n反推回去。
对于
,显然
,所以只有可能通过
或者
其中一种情况推回
,而想到gcd过程就是辗转相除,即辗转相减,因此用gcd()模拟加速相减,就可算出(x,y)得到需要的次数。计算n与1至n-1的gcd()即可。时间复杂度:
反思与总结:
需要改进的:
T1:1.思考贪心算法时一定要证明自己的算法是正确的,或者努力推翻自己的算法,dp能用时就用dp;
2.数据大时要使用读入优化。
T2:1.要注意分析最小值的性质:即遇着最大值就不能再延伸,即用单调栈可以实现。
T3:1.要想涉及到数字的大部分都是数论,不要因为暴力苟且得分就不想数论了。
需要保持的:
T3:打表找规律,然后迭代加深,卡时倒推。考试暴力ac也是奇迹呀(既然想到倒退为啥还没想到gcd?还是对算法不够熟悉呀)