A. 牛牛的三角形
题意:
给
n
条
边
,
是
否
能
找
到
三
条
边
组
成
一
个
三
角
形
给n条边,是否能找到三条边组成一个三角形
给n条边,是否能找到三条边组成一个三角形
题解:
n
<
=
1
e
2
n<=1e2
n<=1e2
由
于
n
很
小
,
直
接
暴
力
枚
举
边
即
可
由于n很小,直接暴力枚举边即可
由于n很小,直接暴力枚举边即可
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int a[110];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++){
if(i==k||i==j||k==j)continue;
if(a[i]+a[j]>a[k]&&a[i]+a[k]>a[j]&&a[k]+a[j]>a[i]){
cout<<a[i]<<' '<<a[j]<<' '<<a[k]<<endl;
return 0;
}
}
cout<<"No solution"<<endl;
return 0;
}
B. 牛牛的鱼缸
题意:
给
一
个
宽
l
高
h
的
鱼
缸
给一个宽l高h的鱼缸
给一个宽l高h的鱼缸
把
他
放
在
一
个
底
边
为
L
,
高
为
H
的
斜
劈
上
,
看
能
装
多
少
水
把他放在一个底边为L,高为H的斜劈上,看能装多少水
把他放在一个底边为L,高为H的斜劈上,看能装多少水
题解:
首
先
需
要
分
类
讨
论
首先需要分类讨论
首先需要分类讨论
看
这
个
鱼
缸
高
度
够
不
够
高
使
得
水
的
形
状
是
梯
形
看这个鱼缸高度够不够高使得水的形状是梯形
看这个鱼缸高度够不够高使得水的形状是梯形
如
果
不
够
,
那
么
则
是
一
个
三
角
形
如果不够,那么则是一个三角形
如果不够,那么则是一个三角形
平
行
内
错
角
相
等
,
形
成
三
角
形
右
边
的
角
和
斜
劈
的
角
是
相
等
的
平行内错角相等,形成三角形右边的角和斜劈的角是相等的
平行内错角相等,形成三角形右边的角和斜劈的角是相等的
三
角
形
的
情
况
说
明
鱼
缸
的
左
臂
一
定
是
全
部
覆
盖
了
,
所
以
三
角
形
的
高
是
h
,
但
低
端
不
一
定
全
部
覆
盖
,
要
根
据
鱼
缸
高
度
来
看
三角形的情况说明鱼缸的左臂一定是全部覆盖了,所以三角形的高是h,但低端不一定全部覆盖,要根据鱼缸高度来看
三角形的情况说明鱼缸的左臂一定是全部覆盖了,所以三角形的高是h,但低端不一定全部覆盖,要根据鱼缸高度来看
已
知
h
和
角
度
又
是
直
角
三
角
形
,
算
一
下
底
边
即
可
知
道
面
积
已知h和角度又是直角三角形,算一下底边即可知道面积
已知h和角度又是直角三角形,算一下底边即可知道面积
然
后
说
梯
形
的
情
况
,
想
象
一
下
梯
形
的
情
况
然后说梯形的情况,想象一下梯形的情况
然后说梯形的情况,想象一下梯形的情况
鱼
缸
左
臂
覆
盖
,
右
臂
覆
盖
一
部
分
,
低
端
全
部
覆
盖
鱼缸左臂覆盖,右臂覆盖一部分,低端全部覆盖
鱼缸左臂覆盖,右臂覆盖一部分,低端全部覆盖
所
以
很
容
易
知
道
,
提
醒
下
底
是
h
,
高
是
l
,
只
要
找
到
上
底
就
行
了
所以很容易知道,提醒下底是h,高是l,只要找到上底就行了
所以很容易知道,提醒下底是h,高是l,只要找到上底就行了
这
个
梯
形
可
以
分
成
一
个
三
角
形
和
一
个
平
行
四
边
形
这个梯形可以分成一个三角形和一个平行四边形
这个梯形可以分成一个三角形和一个平行四边形
整
个
鱼
缸
的
上
部
缺
了
一
个
和
这
个
三
角
形
完
全
一
样
的
三
角
形
就
能
填
满
整个鱼缸的上部缺了一个和这个三角形完全一样的三角形就能填满
整个鱼缸的上部缺了一个和这个三角形完全一样的三角形就能填满
所
以
梯
形
少
了
三
角
形
的
一
个
底
,
这
个
三
角
形
的
高
l
和
角
度
仍
然
是
确
定
的
,
算
底
即
可
所以梯形少了三角形的一个底,这个三角形的高l和角度仍然是确定的,算底即可
所以梯形少了三角形的一个底,这个三角形的高l和角度仍然是确定的,算底即可
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
double h,l,H,L;
cin>>h>>l>>H>>L;
double x=H/L;
if(x>=h/l)
printf("%.9lf",h*h/x/2);
else{
double ans=(h-l*x+h)*l/2;
printf("%.9lf",ans);
}
return 0;
}
C. 牛牛的揠苗助长
题意:
n
块
菜
地
,
每
块
高
度
为
a
i
n块菜地,每块高度为a_i
n块菜地,每块高度为ai
第
一
天
a
1
+
1
,
第
二
天
a
2
+
1
,
第
n
天
a
3
+
1
第一天a_1+1,第二天a_2+1,第n天a_3+1
第一天a1+1,第二天a2+1,第n天a3+1
第
n
+
1
天
a
1
+
1
,
一
次
类
推
第n+1天a_1+1,一次类推
第n+1天a1+1,一次类推
每
一
天
可
以
使
得
每
一
块
地
的
高
度
加
一
或
者
减
一
每一天可以使得每一块地的高度加一或者减一
每一天可以使得每一块地的高度加一或者减一
问
最
少
多
少
天
可
以
使
每
块
地
高
度
一
样
问最少多少天可以使每块地高度一样
问最少多少天可以使每块地高度一样
题解:
这
道
题
大
致
一
看
,
感
觉
是
要
二
分
答
案
来
写
这道题大致一看,感觉是要二分答案来写
这道题大致一看,感觉是要二分答案来写
然
后
思
考
一
下
二
分
答
案
的
可
行
性
然后思考一下二分答案的可行性
然后思考一下二分答案的可行性
如
果
x
是
最
后
的
结
果
,
那
么
x
+
1
那
一
天
增
高
的
高
度
如果x是最后的结果,那么x+1那一天增高的高度
如果x是最后的结果,那么x+1那一天增高的高度
可
以
减
一
去
掉
,
这
样
就
等
于
这
天
什
么
都
没
发
生
可以减一去掉,这样就等于这天什么都没发生
可以减一去掉,这样就等于这天什么都没发生
这
样
就
可
以
看
出
,
即
使
天
数
超
过
结
果
,
最
后
也
是
可
以
达
到
目
的
这样就可以看出,即使天数超过结果,最后也是可以达到目的
这样就可以看出,即使天数超过结果,最后也是可以达到目的
确
定
了
算
法
之
后
,
就
要
写
每
次
答
案
的
判
断
函
数
确定了算法之后,就要写每次答案的判断函数
确定了算法之后,就要写每次答案的判断函数
首
先
把
每
块
地
x
天
之
后
的
高
度
列
出
,
此
时
你
有
x
次
可
以
使
一
块
地
加
减
一
首先把每块地x天之后的高度列出,此时你有x次可以使一块地加减一
首先把每块地x天之后的高度列出,此时你有x次可以使一块地加减一
假
设
你
使
得
所
有
地
成
为
h
高
度
需
要
的
次
数
是
r
e
s
假设你使得所有地成为h高度需要的次数是res
假设你使得所有地成为h高度需要的次数是res
原
本
有
a
块
地
小
于
h
,
b
块
地
大
于
h
原本有a块地小于h,b块地大于h
原本有a块地小于h,b块地大于h
那
么
使
得
所
有
地
成
为
h
−
1
的
次
数
是
r
e
s
+
a
−
b
那么使得所有地成为h-1的次数是res+a-b
那么使得所有地成为h−1的次数是res+a−b
通
过
这
个
可
以
得
出
如
果
只
有
当
a
>
=
b
时
h
的
最
小
值
通过这个可以得出如果只有当a>=b时h的最小值
通过这个可以得出如果只有当a>=b时h的最小值
那
么
就
是
排
序
后
取
得
第
(
n
+
1
)
/
2
小
的
高
度
那么就是排序后取得第(n+1)/2小的高度
那么就是排序后取得第(n+1)/2小的高度
然
后
每
块
地
看
到
这
个
高
度
需
要
多
少
次
,
如
果
次
数
大
于
x
则
不
成
立
然后每块地看到这个高度需要多少次,如果次数大于x则不成立
然后每块地看到这个高度需要多少次,如果次数大于x则不成立
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int n;
ll a[maxn],b[maxn];
bool ok(ll x){
for(int i=1;i<=n;i++){
b[i]=a[i]+x/n;
if(x%n>=i)b[i]++;
}
sort(b+1,b+1+n);
ll y=b[(n+1)/2],res=0;
for(int i=1;i<=n;i++)res+=abs(y-b[i]);
return x>=res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
ll l=0,r=1e18,ans;
while(l<=r){
ll mid=l+r>>1;
if(ok(mid))ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans;
return 0;
}
D. 牛牛的01限定串
题意:
给
定
两
个
01
字
符
串
s
,
t
给定两个01字符串s,t
给定两个01字符串s,t
如
果
某
个
字
符
串
的
每
个
字
符
个
数
等
于
另
一
个
字
符
串
的
每
个
字
符
个
数
如果某个字符串的每个字符个数等于另一个字符串的每个字符个数
如果某个字符串的每个字符个数等于另一个字符串的每个字符个数
那
么
这
两
个
字
符
串
相
似
那么这两个字符串相似
那么这两个字符串相似
字
符
串
t
有
0
,
1
,
?
(
即
不
确
定
)
字符串t有0,1,?(即不确定)
字符串t有0,1,?(即不确定)
如
果
s
,
t
每
有
一
个
前
缀
相
似
,
结
果
加
v
a
l
p
r
e
如果s,t每有一个前缀相似,结果加val_{pre}
如果s,t每有一个前缀相似,结果加valpre
如
果
s
,
t
每
有
一
个
后
缀
相
似
,
结
果
加
v
a
l
s
u
f
如果s,t每有一个后缀相似,结果加val_{suf}
如果s,t每有一个后缀相似,结果加valsuf
字
符
串
t
中
总
共
有
c
n
t
1
个
1
和
c
n
t
0
个
0
字符串t中总共有cnt_1个1和cnt_0个0
字符串t中总共有cnt1个1和cnt0个0
问
最
小
结
果
和
最
大
结
果
分
别
是
多
少
问最小结果和最大结果分别是多少
问最小结果和最大结果分别是多少
题解:
n
<
=
1
e
3
n<=1e3
n<=1e3
范
围
不
是
很
大
,
所
以
可
以
考
虑
二
维
d
p
范围不是很大,所以可以考虑二维dp
范围不是很大,所以可以考虑二维dp
d
p
1
[
i
]
[
j
]
表
示
前
i
个
数
里
有
j
个
1
时
候
的
最
小
结
果
,
d
p
2
[
i
]
[
j
]
为
最
大
结
果
dp1[i][j]表示前i个数里有j个1时候的最小结果,dp2[i][j]为最大结果
dp1[i][j]表示前i个数里有j个1时候的最小结果,dp2[i][j]为最大结果
然
后
用
一
个
前
缀
和
将
s
前
i
位
有
多
少
个
1
维
护
一
下
然后用一个前缀和将s前i位有多少个1维护一下
然后用一个前缀和将s前i位有多少个1维护一下
如
果
j
等
于
此
时
s
的
前
缀
1
了
,
那
么
结
果
加
v
a
l
p
r
e
如果j等于此时s的前缀1了,那么结果加val_{pre}
如果j等于此时s的前缀1了,那么结果加valpre
如
果
c
n
t
1
−
j
等
于
此
时
s
的
后
缀
1
,
加
过
加
v
a
l
s
u
f
如果cnt_1-j等于此时s的后缀1,加过加val_{suf}
如果cnt1−j等于此时s的后缀1,加过加valsuf
然
后
对
第
i
位
为
0
和
为
1
进
行
分
情
况
即
可
然后对第i位为0和为1进行分情况即可
然后对第i位为0和为1进行分情况即可
但
由
于
字
符
串
t
的
一
部
分
已
经
给
出
,
所
以
要
确
保
字
符
串
可
以
等
于
0
或
1
但由于字符串t的一部分已经给出,所以要确保字符串可以等于0或1
但由于字符串t的一部分已经给出,所以要确保字符串可以等于0或1
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
ll dp1[1010][1010],dp2[1010][1010];
int sum[1010];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,c0,c1,vp,vs;
cin>>n>>c0>>c1>>vp>>vs;
string s,t;
cin>>s>>t;
s='.'+s,t='.'+t;
for(int i=1;i<=n;i++){
sum[i]=sum[i-1];
if(s[i]=='1')sum[i]++;
}
for(int i=0;i<=n;i++)
for(int j=0;j<=c1;j++)
dp1[i][j]=1e18,dp2[i][j]=-1e18;
dp1[0][0]=dp2[0][0]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=c1;j++){
ll tmp;
if(t[i]!='1'){
tmp=dp1[i-1][j];
if(j==sum[i])tmp+=vp;
if(sum[n]-sum[i-1]==c1-j)tmp+=vs;
dp1[i][j]=min(dp1[i][j],tmp);
tmp=dp2[i-1][j];
if(j==sum[i])tmp+=vp;
if(sum[n]-sum[i-1]==c1-j)tmp+=vs;
dp2[i][j]=max(dp2[i][j],tmp);
}
if(t[i]!='0'&&j-1>=0){
tmp=dp1[i-1][j-1];
if(j==sum[i])tmp+=vp;
if(sum[n]-sum[i-1]==c1-j+1)tmp+=vs;
dp1[i][j]=min(dp1[i][j],tmp);
tmp=dp2[i-1][j-1];
if(j==sum[i])tmp+=vp;
if(sum[n]-sum[i-1]==c1-j+1)tmp+=vs;
dp2[i][j]=max(dp2[i][j],tmp);
}
}
cout<<dp1[n][c1]<<' '<<dp2[n][c1];
return 0;
}