Codeforces Round #797 (Div. 3) A E F
这是自己打的第二场cf,感觉cf的前几道题就是思维题,有点找规律的意思。
A题
题意:严格满足h1>h2>h3,且答案输出的顺序是h2 h1 h3。
思路:比赛的时候用的是二分(我真是个呆呆)。和队友交流完,知道是用三的倍数来写的(这就有点总结式子,然后找规律,分类判断的意思了)。
1.理想状态下,h1=h2+1=h3+2。这样我们可以由式子h1+h2+h3=sum推出来h1=(sum+3)/3,因此如果(sum+3)能被3整除,那么就满足这个理想情况。
2.如果(sum+3)不能被3整除,也就是sum不能被3整除。那就分类讨论。
E题
题意:给了 n个货品, n 是偶数, 每个货品有价值 ai , 将货品两两配对, 两两配对和总价值为 wi, 给定 k, 求 Σ⌊wik⌋ 最大值
思路:先把每一个货品整除k的值累加到结果res里,同时对每个货物mod k,sort从小到大遍历一遍,用双指针思想,l表示左边,r表示右边。
如果num[i]+num[r]<k,那就说明这两个指针对应的货品配对在一起不能利益最大化(因为他们的余数累加起来达不到k的倍数),l++使得左指针往右走。
反之,res++(说明两个货物可以匹配),l++,r--,这样移动。
#include <bits/stdc++.h> using namespace std; const int N=2e5+100; int a[N],num[N]; typedef long long ll; int main() { int t; cin>>t; while(t--) { int n,k; cin>>n>>k; ll res=0; for(int i=1;i<=n;i++) { cin>>a[i]; res+=a[i]/k; num[i]=a[i]%k; } sort(num+1,num+1+n); int l=1,r=n; while(l<r) { if(num[l]+num[r]<k)l++; else res++,l++,r--; } printf("%lld\n",res); } return 0; }
这道题也可以用stl中的multiset和low_bound() 做。刚查了查,multiset的作用是自动从小到大排序,并且不具有去重功能,可以重复存储相同的数字,时间是logn的。
F题
题意:给定一个长度为 n的字符串 s, 和一个排列 P , 每次操作让 si=sPi , 询问至少经过多少次操作能让字符串与初始状态相同