codeforces round 160(完全)

又跪了。。。继续做吧,坚持!!

codeforces 261B   

先用背包处理出一个dp数组,然后枚举每一个分隔数(即前面的数再加上这个数就超过p了) 统计出所有的数量,然后直接算,,

http://www.codeforces.com/contest/261/submission/2921844


codeforces 261C

首先可以计算出m+1行有几个1 (画一画就能得出规律):即给定一个m,第m+1行的1的个数为2^(bit_count(m+1) - 1 ) 个 ,所以t肯定是2的指数次幂,否则答案为0

现在问题转换成求2到n+1中有几个数的二进制表示中有P+1个1,(2^P = t),典型的数位DP搞一下把。

dp[i][j]表示长度为i有j个1的二进制数的个数,预处理好之后直接统计即可

http://www.codeforces.com/contest/261/submission/2922990


codeforces 261D

我感觉题意好难懂啊。。。。

给你k行数,每行有n个数,然后将这n个数重写t遍相连,问你新组成的序列(总共有n*t个数)的最长递增子序列的长度为多少。

有几个要注意的地方  题目保证所有数都不超过maxb , maxb*n不超过10的7次

CF的服务器比较犀利,好像几个忆的计算量都能飘过,也就是暴力,求出序列后用一个nlogn的求最长递增子序列的算法也可以过

复杂度应该是k * 10^7 * log(maxb) . 

下面贴一种树状数组的做法,相当于用树状数组来优化一个n*maxb的dp

http://www.codeforces.com/contest/261/submission/2951761


上述做法虽然考虑了数列的性质,但还有更好的方法。

膜拜了lzqxh的代码后。。。。thinking。。。。

考虑到数列的性质,长度很长(10^7), 但因为最多只有maxb(10^5)个数,所以我们可以考虑这样的状态 , dp[i]表示以i结尾的最长递增子序列的长度,那么如果当前数为a

当前最长的递增子序列的长度为len,那么我们应该找前面比a小的数b,然后判断一下dp[b]+1能否更新dp[a],什么样的长度能更新dp[a]呢,肯定是dp[a]+1喽,所以应该找长度为dp[a]的且小于a的数接上a,而且如果dp[a]==len+1了,就不用再更新了,因为加入一个a最多能使最长递增序列的长度增加1,既然已经增加1了,就不需要再更新了。

最后有一个很巧妙的做法是用一个数组映射一下dp值为x的最后一个数,即 num[dp[x]] = x; 找长度为dp[a]的数的时候只需要用这个数组直接找就好了。稍微想一下就知道为什么了,tmp = num[dp[a]] 记录的肯定是当前长度为dp[a]的数字(结尾)中最小的数了,因为如果前面还有长度为dp[a]的,且数字小于tmp的那么tmp可以接上去从而tmp处的长度就应该更长才对,而不是dp[a] 。每个dp[i]最多增加cnt次cnt是数字的种类数,所以复杂度是cnt*cnt的,由于cnt<=n,且cnt<=maxb,所以cnt*cnt <= n*maxb <=10^7

http://www.codeforces.com/contest/261/submission/2953464


codeforces  261E

题意:初始的时候给你两个数,1 0    一次操作可以给右边的数+1,也可以将左边的数乘上右边的数再放回左边,问你有多少的数x(l<=x<=r)可以出现左边的位置上,要求操作的次数小于等于p。

注意到p <= 100,可以发现x肯定都是由小于等于100的素数组成的。然后就是题目的突破口了,处理出所有的素因子在100以内的数,1e9以内这样的数大概有300 0000个(尼玛这种范围让我怎么想!!),设dp[i]代表第i个数最少经过几次操作可以得到,那么接下去的事情就是枚举右边操作了几次,直接两重循环暴力去更新dp就好了,dp[j]肯定是由a[k] * i  == a[j],这样 的k更新过来,这里k不用去枚举,将所有的数排序之后利用单调性不断地往右移动就好了。

http://www.codeforces.com/contest/261/submission/2958347



总结:这场比赛DP比较多,思维很灵活,一般都是很简单的DP前面覆盖一层不容易看透的描述(我比较水。。) , 也就是在一般的Dp上加点东西,非常考验思维,,


Codeforces Round 887是一个程序设计竞赛活动,由Codeforces组织举办。根据引用中的代码,该竞赛的题目要求解决一个序列操作的问题。给定一个长度为n的序列,通过执行一系列操作,使得序列变得非sorted,即非严格递增。具体操作是将序列中[1, i]范围内的数字全部加一,同时将[i+1, n]范围内的数字全部减一。问题要求求解最少需要执行多少次操作才能达到要求。 引用中的代码给出了解决这个问题的实现。代码首先读入序列的长度n和序列a。然后通过判断序列是否已经是非sorted,如果是则直接输出0。接下来,代码遍历序列,求出相邻两个数字的差的最小值。最后,计算出最少需要执行的操作次数,并输出结果。 需要注意的是,引用中的代码只是给出了解决问题的一种实现方式,并不代表Codeforces Round 887的具体题目和解答。要了解该竞赛的具体信息,需要参考Codeforces官方网站或相关资料。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Codeforces Round 887 (Div. 2)](https://blog.csdn.net/qq_36545889/article/details/131905067)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值