链接:https://ac.nowcoder.com/acm/contest/3006
来源:2020牛客寒假算法基础集训营5
A 模板
思路:贪心,直接把长串多余的部分都删除,剩下的串中不同的直接修改为相同的即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
char a[maxn],b[maxn];
int main(){
int lena,lenb; scanf("%d%d",&lena,&lenb);
scanf("%s%s",a,b);
int ans=max(lena,lenb)-min(lena,lenb);
for(int i=0;i<min(lena,lenb);i++){
if(a[i]!=b[i]) ans++;
}
printf("%d\n",ans);
return 0;
}
B 牛牛战队的比赛地(二分)
思路:如图
左边图是各个点到赛点的距离,我们刚开始把赛点放在最左边(赛点只能在
x
x
x 轴上面),然后我们把它往右边拉,此时最短距离的最大值就会慢慢变小,等赛点到达某一个极值点的时候这个最短距离的最大值优惠慢慢变大,也就形成了右边的图,此时我们的问题就转化成了求这个函数的极值点的位置,然后输出极值点对应的值即可。二分赛点,然后判断
d
i
s
(
m
i
d
−
e
p
s
)
dis(mid-eps)
dis(mid−eps) 和
d
i
s
(
m
i
d
)
dis(mid)
dis(mid) 也就是比较函数值,函数值就是所有点到达赛点的最大值,如果结果是
<
<
<,那么说明极值点在左边,反之说明极值点还在右边。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const double eps=1e-5;
struct Node{
double x,y;
Node(){}
Node(double x,double y):x(x),y(y){}
}node[maxn];
int n;
double len(Node a,Node b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double dis(double xx){
double mmax=0;
for(int i=1;i<=n;i++){
double disTemp=len(Node(xx,0),node[i]);
mmax=max(mmax,disTemp);
}
return mmax;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf%lf",&node[i].x,&node[i].y);
double l=-10000,r=10000;
while(r-l>eps){
double mid=(l+r)/2;
//cout<<dis(mid-eps)<<" "<<dis(mid)<<endl;
if(dis(mid-eps)<dis(mid)){
r=mid;
}else l=mid;
}
//cout<<l<<endl;
//cout<<dis(l)<<endl;
printf("%.5f\n",dis(l));
return 0;
}
D 牛牛与牛妹的约会(贪心)
思路:贪心直接比较两种走法那个可以缩短时间,哪个需要的时间段就选择哪一种。
#include<bits/stdc++.h>
using namespace std;
int main(){
int T; scanf("%d",&T);
while(T--){
double a,b; scanf("%lf%lf",&a,&b);
double ans=0;
while(1){
double nexta;
if(a>0) nexta=pow(a,1.0/3);
else nexta=-pow(-a,1.0/3);
if(abs(nexta-b)+1.0<abs(a-b)) { ans+=1.0;a=nexta; }
else { ans+=abs(a-b);break; }
}
printf("%.9f\n",ans);
}
return 0;
}
E Enjoy the game(博弈)
思路:在手算这个过程的时候,奇数一定先手必胜,偶数当有奇数个 2 2 2 时一定必胜,这里后手只能和前者取相同的数字,因为一旦取别的数字,一定会将必胜的局面留给下一个人。手动模拟一次,发现只要 n n n 有奇数个 2 k 2^k 2k 先手有必胜策略。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ll n=0; scanf("%lld",&n);
if(n%2==1) puts("Bob");
else{
if(n==2) puts("Alice");
else{
bool flag=false;
ll cnt=n/2,val=2;
while(val*2<n){
if(cnt%2==1) { flag=true;break; }
else { cnt/=2;val*=2; }
}
if(flag) puts("Bob");
else puts("Alice");
}
}
return 0;
}
H Hash(思维+进制转换)
思路:从已知函数给出的算法,我们发现类似于一个 26 26 26 进制转换,由于字符串长度比较小,在不取模的情况下得到的结果也不会爆,那么题目中给出的过程就是就是一个 26 26 26 进制转换,我们先将字符转换成一个 26 26 26 进制的数,然后加模数,最后转化成 6 6 6 位的字符串,最后判断这个 26 26 26 进制数是否为 0 0 0 即可。注意此题目是多组输入。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=10;
char str[maxn],ans[maxn];
int main(){
int mod;
while(~scanf("%s%d",str,&mod)){
ll res=0;
for(int i=0;i<6;i++) res=res*26+str[i]-'a';
res+=mod;
for(int i=5;i>=0;i--){
ans[i]=res%26+'a';
res/=26;
}
if(res) puts("-1");
else puts(ans);
}
return 0;
}
I I题是个签到题
思路:根据题目描述直接判断即可。(题目描述看的有点模糊)
#include<bits/stdc++.h>
using namespace std;
const int maxn=15;
int a[maxn],b[maxn];
int main(){
int n,m; scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int pro=((double)a[9]/m)*100;
if(pro>=80) puts("Yes");
else{
int a9=a[9]; bool flag=false;
sort(a+1,a+n+1,greater<int>());
for(int i=1;i<=n;i++){
if(i<=3&&a9>=a[i]){
flag=true;
break;
}
}
if(flag) puts("Yes");
else puts("No");
}
return 0;
}
J 牛牛战队的秀场(数学)
思路:直接使用余弦定理就可以算出边长,最后成两点之间的距离即可。最短距离 m i n ( 顺 时 针 , 逆 时 针 ) min(顺时针,逆时针) min(顺时针,逆时针)
#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1.0);
int main(){
double n,r; scanf("%lf%lf",&n,&r);
int i,j; scanf("%d%d",&i,&j);
double c2=r*r+r*r-2*r*r*cos(2*pi/n);
double c=sqrt(c2);
double ans=c*(min((double)abs(i-j),n-abs(j-i)));
printf("%.6f\n",ans);
return 0;
}