牛客小白月赛67 A-F 补题
A 画牌河 签到
void Showball(){
int n;
cin>>n;
for(int i=0;i<3;i++){
for(int j=0;j<6;j++){
if(n>0) cout<<1;
else cout<<0;
n--;
}
cout<<endl;
}
}
B&D 不点两面 模拟
B题是D题的简单版本,赛时直接按照D的数据范围写的。
题意:给你1-m之间的数,有两种操作,第一种操作,给定一个x,
标记x-3和x+3。第二个操作,给定一个x,去除x。每次操作完都需要输出1-m中被标记数的个数。
思路:我们用一个桶去统计每个数被标记的次数,并且将标记的数维护在一个set中,去除操作时,我们只需要将次数减一即可。次数减为0的时候,我们把该数从set中删去即可。
void Showball(){
int m,q;
cin>>m>>q;
set<int> s;
map<int,int> mp;
auto in = [&](int x) {return 1<=x&&x<=m;};
while(q--){
int op,num;
cin>>op>>num;
if(op==1){
if(in(num-3)) mp[num-3]++,s.insert(num-3);
if(in(num+3)) mp[num+3]++,s.insert(num+3);
}else{
if(in(num-3)) if(!--mp[num-3]) s.erase(num-3);
if(in(num+3)) if(!--mp[num+3]) s.erase(num+3);
}
cout<<s.size()<<endl;
}
}
C 一刀二分三角 数学+枚举
题意:给你三个点分别是(0,0),(xb,0),(xc,yc)构成的三角形,并且
x
b
>
x
c
xb>xc
xb>xc。让你去判断有没有可能从x=x0处分割这个三角形使得平分三角形的面积。
思路:数据范围比较小,我们可以直接枚举即可。分为0-xc,xc+1-xb这两个部分。面积公式就是初中数学知识。这里为了防止精度问题,在判断时,全部转化为除法来进行。
void Showball(){
LL xb,xc,yc;
cin>>xb>>xc>>yc;
LL s=xb*yc,d=xb-xc;
bool flg=false;
for(int i=0;i<=xc;i++){
if(2*yc*i*i==s*xc) {flg=true;break;}
}
for(int i=xc+1;i<=xb;i++){
if(2*(s*(xb-i)-yc*i*(xb-i))==s*d) {flg=true;break;}
}
if(flg) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
E 游戏的买 期望dp
题意:小明想要买一款游戏,每天的价格有两个可能的值
a
i
a_i
ai和
b
i
b_i
bi,概率均为0.5。求出小明保证能买到该游戏的前提下,期望会花多少钱。
思路:期望dp,我们倒着进行考虑。
状态表示:
d
p
[
i
]
dp[i]
dp[i]表示前i-1天都不买考虑i-n天的情况,期望的最低购买价格。
在第
i
i
i天有0.5概率价格为
a
i
a_i
ai,还需要比较dp[i+1],选更小的情况。
b
i
b_i
bi的情况同理。
转移方程:
d
p
[
i
]
=
0.5
∗
m
i
n
(
a
[
i
]
,
d
p
[
i
+
1
]
)
+
0.5
∗
m
i
n
(
b
[
i
]
,
d
p
[
i
+
1
]
)
dp[i]=0.5∗min(a[i],dp[i+1])+0.5∗min(b[i],dp[i+1])
dp[i]=0.5∗min(a[i],dp[i+1])+0.5∗min(b[i],dp[i+1])
void Showball(){
int n;
cin>>n;
vector<double> a(n+1),b(n+1),dp(n+2);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
dp[n+1]=inf;
for(int i=n;i>=1;i--){
dp[i]=0.5*min(dp[i+1],a[i])+0.5*min(dp[i+1],b[i]);
}
cout<<fixed<<setprecision(6)<<dp[1]<<endl;
}
F 翼伯父作威
题意:给你一个坐标(x,y)。两人轮流进行游戏,每次每个人可以向左(x-k,y),向下(x,y-k),向左下(x-k,y-k)。谁先走到(0,0)谁就赢得了游戏,设一共进行了c回合游戏。每人初始有1e9元,输家需要给赢家1e9-c元。计算赢家最多可以有多少元?
思路:经过一些手算研究,我们可以得到一些必败态,比如(1,2),(3,5),(4,7)…我们发现坐标之差的绝对值值逐渐递增的。并且横坐标是之前的数中没有出现的最小的数。很明显符合威佐夫博弈的性质。每个必败点我们用
a
b
s
(
x
−
y
)
abs(x-y)
abs(x−y)来标号。
我们可以预先处理出所有的必败点。
对于(x,y)是必败点。那么它最多能走
2
∗
a
b
s
(
x
−
y
)
2*abs(x-y)
2∗abs(x−y)步。可以画图分析一下。
对于(x,y)不是必败点。那么我们就需要从三个方向去寻找有无必败点,然后走到必败点。因为我们需要赚更多的前,就需要越早结束游戏越好。那么我们就需要到最小的必败点。
具体处理是学习大佬的代码。非常简洁。
vector<int> vis(2*N+1);
void init(){
int cnt=1;
vis[0]=0;
for(int i=1;i<=N;i++){
if(!vis[i]){
vis[i+cnt]=i;
vis[i]=i+cnt;
cnt++;
}
}
}
void Showball(){
int x,y;
cin>>x>>y;
int c=2*abs(x-y)+1;
if(x==vis[y]||y==vis[x]) c=min(c,2*abs(x-y));
if(y>vis[x]) c=min(c,2*abs(x-vis[x])+1);
if(x>vis[y]) c=min(c,2*abs(vis[y]-y)+1);
cout<<inf-c<<endl;
}
1336

被折叠的 条评论
为什么被折叠?



