目录
A. 命题人的疏忽(构造 / 交互)
翻译:
思路:
代码:
B. 社恐的舞会 I(构造)
思路:
代码:
D. 开灯(签到)
思路:
代码:
E. 社恐的舞会 II(构造 / 数学)
思路:
代码:
G. 切蛋糕(签到 / 构造)
思路:
代码:
H. 套娃(CDQ分治)
思路:
代码:
I. 宝箱(线性dp)
思路:
代码:
这是一道交互题。
Cuber QQ 正在做 CuberOJ 上的一道难题。这是一道有着 n 组评测数据的传统算法竞赛题,每组测试数据的第一行都是一个整数,表示这组测试数据的编号:第一组数据的第一行是一个 1,第二组数据的第一行是一个 2,以此类推。每组测试数据的答案都是 0 或 1。
CuberOJ 的评测机制与 ICPC 竞赛类似。它会按照编号逐一使用评测数据来测试提交的程序。如果选手的程序通过了一组评测数据,那么评测机会继续评测下一组数据;而如果选手的程序输出了错误的答案,那么评测机会反馈WA
并且不再进行后续的评测。如果在使用某组数据进行评测时,程序发生了运行错误(比如除零、数组越界导致的段错误),那么评测机会反馈RE
并同样不再进行后续评测。如果程序通过了所有的测试数据,那么评测机会反馈AC
。
CuberOJ 与 EOJ 不同,它并不会告诉 Cuber QQ 具体错在第几个测试点,而只会反馈一个最终结果——AC
、WA
或者RE
。Cuber QQ 觉得,如果他能够知道他的程序在第几个测试点WA
了,那么他就能够很轻松地试出所有测试数据的答案。
在 Quber CC 的指点下,Cuber QQ 发现,如果他在某些测试数据上故意构造一句导致RE
的语句,就可以间接地推断出一些信息。所以即便 CuberOJ 不告诉他具体发生错误的测试点编号,他也有方法试出所有正确的答案。而现在,帮助 Cuber QQ 试出正确答案的重任落到了你的头上。你可以进行多次尝试,每次尝试你可以用一行 n 个整数来表示你的程序的构造方式:0 表示让你的程序输出 0,1 表示让你的程序输出 1,而 −1 则表示你故意构造一个RE
。比如,如果你想构造以下这个程序,请输出0 1 -1
。
input(n);
if (n == 1) print(0);
if (n == 2) print(1);
if (n == 3) n = n / 0;
在你的每次尝试后,交互器会告诉你这个程序的运行结果,AC
或者WA
或者RE
。如果你得到了一个AC
,请立即结束你的程序,并且你会通过本题的一个测试点。
请注意,你最多有 n+1 次尝试机会。如果你没能在这 n+1 次尝试中输出完全正确的答案,那么你无法通过此题。
输入格式
在交互开始前,你需要先读入一个整数 n (1≤n≤100),表示测试数据的组数。
然后你可以开始交互。请你在一行中输出 n 个整数,每个整数都是 0,1,−1 之一,分别表示你想对对应的一组测试数据构造答案 0、构造答案 1、或构造一句会导致RE
的语句。
对于你的每一次尝试,交互器都会在单独的一行中输出运行结果:AC
或者WA
或者RE
,表示你构造的程序的运行结果。因此,当你的程序输出结束后,你都应该读入交互器返回的信息。如果你读到了AC
,请立即终止你的程序,否则可能会被判定为超时。
输出格式
请注意,你需要在每输出一行之后执行 flush
操作,否则你提交的程序有可能会被判定为Idleness limit exceeded
。
适用于各种语言的flush
函数如下:
fflush(stdout);
System.out.flush();
flush(output);
sys.stdout.flush()
样例
input
5 RE WA AC
output
1 0 1 1 -1 1 0 1 1 1 1 0 1 1 0
提示
样例解释:
假设 5 组测试数据的正确答案分别是1 0 1 1 0
。
首先,交互器向选手程序输入5
,即数据的组数。选手程序猜测前 4 组数据是1 0 1 1
,并在第 5 组构造一个RE
,因此输出1 0 1 1 -1
。前 4 组答案正确,第 5 组RE
,因此交互器向选手程序输入结果RE
。
接着,选手程序猜测前5组数据是1 0 1 1 1
,输出1 0 1 1 1
,由于前4组答案正确、第5组答案错误,因此交互器向选手程序输入WA
。
最后,选手程序输出1 0 1 1 0
。答案全部正确,交互器向选手程序输入AC
。此时选手程序需要自行终止(否则会超时)。
有一串0和1组成的数列,你要猜出来它:
从第一位开始,把你的数列和答案数列作比较,如果不一致反馈一个WA,如果你给的是-1,返回一个RE,如果去全部一样,返回AC
要求在不超过n+1次猜测中把得到AC
交互题,构造数列全部为-1,然后一位一位地改为0
如果返回WA,说明这位应该是1,如果返回RE,说明就是0
出现AC退出即可
#include
using namespace std;
typedef long long ll;
int main(){
int n;
cin>>n;
int flag=0;
vectora(n+3,-1); //构造全是-1
int cnt=1;
while(1){
string s;
a[cnt++]=0; //一位一位赋值为0
for(int i=1;i<=n;i++)cout<>s;
if(s=="AC"){
return 0;
}
if(s=="RE"){ //就是0
continue;
}
if(s=="WA"){ //应该是1
a[cnt-1]=1;
}
}
return 0;
}
Cuber QQ 是一位社交恐惧者。为了显得他并没有那么害怕社交,他打算请他的 n 位社恐朋友们开一场舞会。
Cuber QQ 准备了一个超大的舞池。这个舞池可以看作一个平面直角坐标系,因为 Cuber QQ 喜欢整齐划一的感觉,所以他想把每个朋友安排在一个格点上。当然,他可以在一个格点上安排多位朋友。
Cuber QQ 觉得,这些社恐朋友们肯定不希望这场舞会过于拥挤。以 Cuber QQ 的经验,社恐们只会和与自己直线距离小于或等于 1 的人们社交。而且,一旦和超过 2 人社交,他们就会非常尴尬,不知所措。然而,如果和小于 2 人社交,他们就会觉得自己被孤立了,很有可能心生不满。所以,每个人必须恰好和 2 人社交,不多不少。
考虑到这些要求,位置的安排就非常困难了。Cuber QQ 会告诉你参加舞会的人数,想让你帮忙给一个方案。
以下是一段形式化的题目描述。
请在平面直角坐标系中放置 n 个格点 ,使得对于其中任何一个点 ,都恰好有 2 个点(不包括 i 自己)与 它 的欧几里得距离小于等于 1。你可以在同一个坐标上放置多个点。
输入格式
输入一个整数 n (1≤n≤103),表示参加舞会的人数。
输出格式
如果不存在满足条件的方案,请输出 −1。
否则,请输出 n 行,每行包含两个正整数 xi,yi(1≤xi,yi≤103),表示第 i 位朋友在舞池中的坐标。如果有多种解,输出其中任意一种即可。
样例
input
1
output
-1
input
4
output
1 1 1 2 2 1 2 2
提示
格点是指横纵坐标都是整数的点。
注意到三个数放在一起可以组成一个小团伙,四个人放一个正方形可以组成一个小团队
对1,2,5特判一下-1
然后所有数模4有四种情况:0,1,2,3
0可以全部拆成4人
1相当于(n-9)%4==0 ,拆成三个3人和一堆4人
2相当于(n-6)%4==0 ,拆成两个3人和一堆4人
3拆成一个3人和一堆4人
#include
using namespace std;
typedef long long ll;
int main(){
int n;
cin>>n;
if(n==1||n==2||n==5){ //特判
cout<<-1;
return 0;
}
if(n%4==0){
int cnt=n/4;
for(int i=0;i
Cuber QQ 为他的舞池准备了一条灯带,灯带上有 n 个 LED 灯。灯带的主控芯片上有 n 个非常小的按钮,分别控制每一盏灯。按下一个按钮后,对应的 LED 灯就会改变状态:由开变关,或由关变开。
初始状态下,所有的灯都处于关闭状态。舞会即将开始,Cuber QQ 想要把所有的灯都打开。可是他发现,由于按钮太小,他每次尝试去点击时,都会一下子按下连续的 m 个按钮。他想问问你,他是否能够把所有的灯都同时打开?
输入格式
输入一行两个整数 m 和 n(1≤n≤m≤106),分别表示灯的数量和 Cuber QQ 一次按下的按钮数。
输出格式
如果能点亮所有的灯则输出 Yes
,否则输出 No
。
样例
input
10 5
output
Yes
提示
样例中,Cuber QQ 可以先按下前 5 个按钮,再按下后 5 个按钮,这样就打开了所有的灯。
灯的个数能被一次开灯的次数整除,则可以全部打开,否则总会有开不了的灯
#include
using namespace std;
typedef long long ll;
int main(){
int n,m;
cin>>n>>m;
int flag=0;
if(n%m==0)flag=1;
if(flag)cout<<"Yes"<
Cuber QQ 的舞会最后搞得一团糟。他似乎高估了他的社恐朋友们的社交意愿,不少朋友们看见这一千人的大场面就被吓得不敢进门。更糟糕的是,租下这个一百万平方米的大舞池花光了 Cuber QQ 的全部积蓄。
Cuber QQ 并不甘心他的舞会计划就此失败。他痛定思痛,好好反思,终于找到了问题所在。首先,千人舞会给社恐们带来的压力还是太大了,他决定缩小舞会的规模,只邀请他最要好的 16 位朋友前来。其次,上次舞会给每位朋友安排了两位社交对象,这对于极端社恐来说仍然十分困难。所以这次,任意两人之间至少间隔两米,给这些社恐朋友们更宽松的社交距离。最后,考虑到经济问题,这次他只能找一个小一点的舞池,于是他租下了一个半径为 9.5 米的 90 度扇形舞池。因为大家不喜欢被孤立的感觉,所以每个人离舞池边缘的距离也要大于 1 米。
所以这次,你的任务是在一个半径为 9.5 米的 90 度扇形中放置 16 个互不重叠的半径为 1 的圆。为了方便各位输出答案,我们将这个扇形放入一个平面直角坐标系中,扇形的两条边分别和 x 轴与 y 轴的正方向重合。请输出这 16 个圆的圆心的坐标。
输入格式
本题没有输入。
输出格式
输出包含 16 行,每行包含两个用空格分隔的实数 xi,yi,表示每个朋友的位置。需要满足
本题答案不唯一,输出任意一组即可。
从第一层开始一层一层往上垒,按照半径1.001算,层高是根号3,如果到圆心距离大于8.5则下一层,直到数出16个圆
#include
using namespace std;
typedef long long ll;
int main(){
int layer=1;
vector >a;
while(a.size()<16){
double y=sqrt(3)*1.001*(layer-1)+1.001; //层高
if(layer%2==1){ //奇数层
for(double i=1.001;i<=9.5;i+=2.002){
if(sqrt(i*i+y*y)<=8.5){
a.push_back(make_pair(i,y));
if(a.size()==16)break;
}
}
}
else{
for(double i=2.002;i<=9.5;i+=2.002){ //偶数层
if(sqrt(i*i+y*y)<=8.5){
a.push_back(make_pair(i,y));
if(a.size()==16)break;
}
}
}
layer++;
}
for(auto it:a){
cout<
Cuber QQ 为 Quber CC 买了两个生日蛋糕,一个是草莓味的,另一个也是草莓味的。
Cuber QQ 把这两个蛋糕放在了餐桌上,他想只切一刀就把这两个蛋糕同时切成面积相同的两半。每个蛋糕,一半他吃,一半 Quber CC 吃。
我们可以把这两个蛋糕看作是平面直角坐标系中的两个矩形,矩形的边都平行于 x 轴或 y 轴。请找到一条直线可以同时平分这两个矩形的面积。我们将给出每个矩形一对对角的顶点的坐标来确定矩形的位置。
输入格式
输入包含两行,每行包含四个整数 x1,y1,x2,y2(−103≤x1,y1,x2,y2≤103),表示该矩形的一对对角的顶点的坐标。
输出格式
数据保证答案存在且唯一,且可以用 y=kx+b 的形式表示。
第一行请输出一个实数表示直线斜率 k。
第二行请输出一个实数表示直线的截距 b。
样例
input
0 0 2 2 -1 -1 -2 3
output
0.00000000 1.00000000
提示
保证答案直线不平行于 y 轴。如果输出的答案与标准答案的绝对或相对误差小于 10−4 我们便认为答案正确。
连接两个矩形重心即可
#include
using namespace std;
typedef long long ll;
int main(){
double x1,x2,x3,x4,y1,y2,y3,y4;
cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;
double tmp1=(x1+x2)/2;
double tmp2=(y1+y2)/2;
double tmp3=(x3+x4)/2;
double tmp4=(y3+y4)/2;
double ans1,ans2;
ans1=(tmp4-tmp2)/(tmp3-tmp1);
ans2=tmp2-ans1*tmp1;
cout<
Cuber QQ 想为 Quber CC 的生日准备一件礼物。他买了 n 个套娃,第 i 个套娃的长度、宽度、高度分别是 a,b,c,重量是 wi 。当且仅当 ai Cuber QQ 想要给 Quber CC 送一个他所能组装成的最重的套娃(内部可能套了许多层),请你告诉他最重的套娃有多重。 输入格式 第一行包含一个整数 n(1≤n≤105),代表套娃的数量。 接下来的 n 行,每行包含四个整数 a,b,c,w ,表示第 i 个套娃的长度、宽度、高度。其中 1≤a,b,c≤109, 0≤w≤109。 输出格式 输出共一行,包含一个整数,表示组装成的最重的套娃有多重。 input output 提示 在样例中,Cuber QQ 可以将第一个套娃放进第四个套娃 ,然后把第四个套娃放进第三个套娃。组装成的套娃重量是 6 。 CDQ分治,三维严格单调(类似偏序)问题 首先按照第一维排序,降一维,然后利用分治思想,将区间分为两半,各自按照第二维排序,而左区间内的第一维小于右区间的第一维,再降一维 对于第三维,我们使用树状数组进行降维,树状数组 tr[i] 表示第三维为 i 的套娃最大能装的重量,每次使用完将树状数组情况,注意要离散化处理,详见代码注释 Cuber QQ 的《弈!悟!》一上线就成为了爆款手游。为了留住更多的活跃用户,Cuber QQ 准备设计一些奖励机制,吸引用户每天按时登陆游戏。 Cuber QQ 推出了一场 n 天打卡活动,玩家每天登陆游戏就可获得一个红色宝箱和一个蓝色宝箱。红色宝箱和蓝色宝箱中均可开出一定数额的金币(金币数额一定是正整数)。而且随着连续打卡天数的增加,奖励会越加丰厚。在第 i+1 天的红色宝箱中开出的金额一定高于第 i 天的红色宝箱。同样地,第 i+1 天的蓝色宝箱中开出的金额一定高于第 i 天的蓝色宝箱。 核心玩家们肯定不会错过每一天的宝箱,一个全勤的玩家可以获得全部的 2n 个宝箱。Cuber QQ 为了给玩家一点惊喜,他想,这所有的 2n 个宝箱中的金币数应当互不相同;而且他想指定这其中某几个箱子一定会开出奇数数目的金币,其余的箱子一定会开出偶数数目的金币。 当然,Cuber QQ 也不想让玩家在一个箱子中获得太多的金币。他想问问你,在满足这些要求的前提下,如何安排每个宝箱开出的数额,可以使得一个玩家在单个宝箱中获得的金币的最大值尽可能小。 输入格式 第一行包含一个整数 n(1≤n≤1000),表示登陆活动的天数。 第二行包含 n 个整数 a1,a2,…,an,ai=0 表示第 i 天的红色宝箱一定开出偶数枚金币,ai=1 表示第 i 天的红色宝箱一定会开出奇数枚金币。 第三行包含 n 个整数 b1,b2,…,bn,bi=0 表示第 i 天的蓝色宝箱一定开出偶数枚金币,bi=1 表示第 i 天的蓝色宝箱一定会开出奇数枚金币。 输出格式 输出共一行,包含一个整数,表示一个玩家在单个宝箱中获得的最多的金币数的最小值。 样例 input output 提示 在样例所述的情况中,我们可以让每天的红色宝箱分别开出 1、2、4、5、7 枚金币,每天的蓝色宝箱分别开出 6、8、10、11、12 枚金币,这样玩家在单个宝箱中最多获得 12 个金币。在其他的方案中,玩家在单个宝箱中开出的金币数的最大值都不会小于 12。 线性dp,dp[i][j]表示开了第i个红色和第j个蓝色宝箱的情况 每次用前一个宝箱更新,如果和当前宝箱奇偶相同,则用+2更新,否则用+1更新
5
1 2 3 1
2 2 2 2
3 4 5 3
2 3 4 2
3 3 3 3
6
思路:
代码:
#include
I. 宝箱(线性dp)
5
1 0 0 1 1
0 0 0 1 0
12
思路:
代码:
#include