【解题报告】CF Round #320 (Div. 2)

Raising Bacteria

题意:盒子里面的细菌每天会数量翻倍,你可以在任意一天放任意多的细菌,最后要使得某天盒子里面的细菌数量等于x,求至少要放多少个细菌

思路:显然,翻倍即为二进制左移一位,那么放入一个细菌,到第二天就变成2个二进制下即为1->10对于任意二进制数 如:1001110,只需要在第一天放1个,第4、5、6天各放一个,再等一天,就可以了。所以答案显然是x在二进制下1的个数。

Finding Team Member

题意:2n个人,每两个人组合的队伍有aij的力量。每个人都希望组合的队伍力量最大。求最终会怎么组合。

思路:找出矩阵中最大的那个数字aij,显然ij会组成一队,然后ij已经组队了,把和ij有关的行列都删除,然后再找出剩下的最大组合。依次类推即可以出答案。

直接在矩阵中找显然会超时。我们可以把矩阵的每条排序,然后从大到小依次扫描并标记每个人的队友,扫描到一个值的时候先判断对应的ij是否已经组队,如果已经组队就跳过这一项。

A Problem about Polyline

题意:折线经过点(0, 0) – (x, x) – (2x, 0) – (3x, x) – (4x, 0) – ... - (2kx, 0) – (2kx + x, x) – ...。给定一个坐标(a,b)求最小的x使得折线经过点(a,b)。

思路:先计算出经过那点之后第一次碰到x轴的位置的坐标(a+b,0),然后求出这个点的x坐标在总的几分点上。即(a+b)/b。然后向上取到2的倍数,即为这段折线有多少条线段组成。然后就可以计算x了。

"Or" Game

题意:给定一个数列,你可以操作k次,每次选择其中的一个数字把它乘以x,求这样操作完成后,使所有数字进行或运算的结果最大。

思路:考虑所有数字的二进制。如果有一个数字的二进制位数最大,那么一定是把所有操作都用在这个数字上,因为乘以x之后这个数字的二进制位数会增加,而且所有数字或运算后结果的二进制位数等于这个数列里面最大的二进制位数,因此把所有操作用在那个本来就最大的二进制位数上的话,二进制位数就会最大(因为x大于等于2)。

这样考虑完之后,如果有多个数字的二进制位数最大且相同呢?那么首先考虑第一次操作肯定会操作在这些数字的某一个上,而且操作完之后,这个数字就变成唯一一个二进制位数最大的了,那么接下来的操作肯定也是在这个数字上的,所以可以得出结论,k次操作都会用在同一个数字上!

至于哪一个,直接遍历就好了~

值得注意的是,遍历的时候,可以先预处理出o[i]=a[0]|a[1]|...|a[i-1]|a[i+1]|a[i+2]|...|a[n-1],这一步可以O(n)完成,然后计算出第i个位置的值再和o[i]取或。

o[i]的话,先预处理出左半边:a[0]..a[i-1],再处理右半边a[i+1]...a[n-1]。分两步正反各扫描一次即可完成。

Weakness and Poorness

题意:给定一个序列a1~an,求一个x使得a1-x,a2-x,...,an-x的 weakness  最小。

weakness 定义为序列的 最大的 子序列的poorness

poorness是这个序列的和的绝对值

思路:假定只有一个序列,我们求一个x使得这个序列的poorness最小。把x作为自变量,这个poorness的结果作为函数f(x)的话,可以得知f(x)是个凸函数(先增大,后变小,中间可能有一段不变)。

于是我们要求的问题变成 g(x)=min(f1(x),f2(x)...)。可以得知g(x)也是凸函数。g(x)这个函数的函数值可以通过dp求解。就是最大连续子段和的dp啦。

于是问题就是求g(x)这个凸函数的极值问题了,直接套三分求解即可。

PS:这题的精度卡的有点紧。。。

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<map>
#include<queue>
#include<set>
using namespace std;
#define CIN(x) scanf("%d",&x)
#define FOR(i,n) for(i=0;i<(n);i++)
#define CLR(a,v) memset(a,(v),sizeof(a))
int a[200005];
int n;
double f(double x){
    double ans1=0,ans2=0;
    double ansans1=0,ansans2=0;
    for(int i=0;i<n;i++){
        ans1=max(ans1+(a[i]-x),(a[i]-x));
        ansans1=max(ans1,ansans1);
        ans2=min(ans2+(a[i]-x),(a[i]-x));
        ansans2=min(ans2,ansans2);
    }
    return max(ansans1,-ansans2);
}
double sanfen(double l,double r){
    double mid,midmid,fmid,fmidmid;
    mid=(l+r)/2;
    midmid=(mid+r)/2;
    fmid=f(mid);
    fmidmid=f(midmid);
    while(r-l>0.00000000001){
        if(fmid>fmidmid){
            l=mid;
            mid=midmid;
            fmid=fmidmid;
            midmid=(mid+r)/2;
            fmidmid=f(midmid);
        }else{
            r=midmid;
            midmid=mid;
            fmidmid=fmid;
            mid=(l+midmid)/2;
            fmid=f(mid);
        }
    }
    return fmid;
}
int main(){
    CIN(n);
    int ma=-10000,i;
    int mi=10000;
    FOR(i,n){
        CIN(a[i]);
        ma=max(a[i],ma);
        mi=min(a[i],mi);
    }
    printf("%.12lf\n",sanfen(mi,ma));
    return 0;
}

最后一题并不会做。。。

时间: 2024-12-24 17:43:58

【解题报告】CF Round #320 (Div. 2)的相关文章

cf Round#273 Div.2

题目链接,点击一下 Round#273 Div.2 ================== problem A Initial Bet ================== 很简单,打了两三场的cf第一次在10分钟内过题 判平均数,且注意b为正 1 #include<iostream> 2 using namespace std; 3 int main() 4 { 5 int res = 0,n; 6 for(int i = 0; i < 5; i++) 7 { 8 cin>>

【codeforces】【比赛题解】#854 CF Round #433 (Div.2)

cf一如既往挺丧 看丧题点我! [A]分数 Petya是数学迷,特别是有关于分数的数学.最近他学了所谓一个分数被叫做"真分数"当且仅当其分子小于分母,而一个分数被叫做"最简分数"当且仅当其分子分母互质.在闲暇时间,Petya在用计算器研究:如何把最简真分数转换为小数等问题.有一天他不小心把除号(÷)按成了加号(+),导致他得到了分子与分母的和.Petya想要得到他原来的分数,但他很快发现这不是唯一的.所以现在他想要知道最大的最简真分数使得其分子与分母的和为n. 输入

codeforces Round #320 (Div. 2) C. A Problem about Polyline(数学)

解题思路: 我们可以发现这样的一个规律: (1)首先b一定要小于a,否则无论如何曲线也无法通过(a,b); (2)设int k=a/b, 如果k为奇数,说明这个点在上图的绿色的线上, 没关系,我们让 k+=1:这样的话一定有(0,0), (a,b)这两点确定的直线的 斜率1/k介于(1/(k-1),  1/(k+1))之间,那么我们可以通过缩小(或者放大)X的值,使得第 k/2 个周期块 斜率为-1的那条边经过(a, b).此时 的X值就是最小的! (3)如果(a,b)在第 k/2 个周期块 斜

【codeforces】【比赛题解】#849 CF Round #431 (Div.2)

cf的比赛越来越有难度了--至少我做起来是这样. 先看看题目吧:点我. 这次比赛是北京时间21:35开始的,算是比较良心. [A]奇数与结束 "奇数从哪里开始,又在哪里结束?梦想从何处起航,它们又是否会破灭呢?" 给定一个长度为n的序列.确定能不能将序列分成奇数个长度为奇数的非空字串,而且这其中每个子串以奇数开头,以奇数结尾.可以只分成一个(1也是奇数). 输入 第一行一个正整数n,表示序列长度. 第二行n个整数,表示序列中的元素. 输出 输出"Yes"或"

Codeforces Round #320 (Div. 2) &quot;Or&quot; Game(好题,贪心/位运算/前缀后缀或)

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 using namespace std; 6 typedef long long ll; 7 /* 8 n个数,你最多有k次操作,每次操作可以选择一个数乘以x,问所有数或(|)的最大值 9 贪心思路:选一个数进行k此乘以x操作; 因为x>=2 10 111 ---> 1111 11

Codeforces Round #320 (Div. 2) [Bayan Thanks-Round]

一部分题解,算是自己SB了 上午的TC 也是这样 写好了代码,却一直没注意细节,然后以为错了. 此处省100字,ps 貌似紫了,作为一个老菜鸡,终于紫了 A,B 都是语文题 C: 给以一个三角形一样的图,判断点(a,b)是否在图中,我是这样判断的: 前一半是k*2*x+b=a;求最小的x,这里二分,但是注意k=0,所以你特判掉: 后一半是:2*(k+1)=a+b;二分类似 D:坐等官方题解,不靠谱系列:我试了很多方法: 做法:只可能是一个数*x^k: 之前以为是最大数*x^k ,但是错的 想想:

CF Round #354(Div.2)

A 输入一个数组,数组元素只能交换一次,求最大值与最小值之间的最大距离.(后来才发现看题目不认真,最小值为1,最大值为n...) #include<iostream> #include<cstring> #include<algorithm> using namespace std; int num[110]; int main() { int n; while(cin>>n) { int mmax=-1,mmin=10,maxflag=-1,minflag

CodeForces #Round 320 (div 1) 简要记录

A 题意: 目前平面上有一条折线,其通过的点分别为(0,0)->(x,x)->(2x,0)->(3x,x)-.. x等于1的时候大概就是这样子 然后给定一个整数点(a,b) 询问最小的x值使折线经过这个点. 解析: 好吧其实我一直以为这是一个结论题,然后一直想有没有什么神奇的结论,结果被数学公式D的飞起. 首先a a==b直接输出a即可. a>b的时候, 有两种可能,第一种是y=x-(a-b) 另一种是y=-x+(a+b) 我们先感受一个情况,所有由斜率为1的直线经过的点都可以用斜

Codeforces Round #320 (Div. 1) [Bayan Thanks-Round] A A Problem about Polyline

题目中给出的函数具有周期性,总可以移动到第一个周期内,当然,a<b则无解. 假设移动后在上升的那段,则有a-2*x*n=b,注意限制条件x≥b,n是整数,则n≤(a-b)/(2*b).满足条件的x≥(a-b)/(2*n) 假设在下降的那段,2*x-(a-2*x*n)=b,n+1≤(a+b)/(2*b),x≥(a+b)/(2*(n+1)) 两者取最小值 #include<bits/stdc++.h> using namespace std; int main() { int a,b; sc