A 模板
题目很简单,要求的答案包括两部分:两个字符串长度的差num1和在短的字符串长度上,循环两者有num2个不同的字母,num=num1+num2;
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=1e5+10;
char a[maxn];
char b[maxn];
int main()
{
ll n,m;
cin>>n>>m;
cin>>a>>b;
ll n1=sizeof(a);
ll n2=sizeof(b);
ll mi=0;
mi=n1>n2?n2:n1;
ll num=n1+n2-2*mi;
for(int i=0;i<n1;i++){
if(a[i]!=b[i])
num++;
}
cout<<num<<endl;
return 0;
}
B 牛牛战队的比赛地
这个题我一开始没想上,后来看了题解才知道可以用二分、三分的方法来解问题:
三分比较好想,只要函数有峰值,就可以用三分,在二分查找的基础上,在右区间(或左区间)再进行一次二分,这样的查找算法称为三分查找,也就是三分法:与二分法类似,先取整个区间的中间值mid;再取右侧区间的中间midmid,从而把区间分为三个小区间。 比较mid与midmid谁最靠近最值,只需要确定mid所在的函数值与midmid所在的函数值的大小。当最值为最小值时,mid与midmid中较小的那个自然更为靠近最值。最值为最大值时同理。
二分的方法是从0-500000,将mid=(l+r)/2,调整后check(mid):如果(a[i].x)^2 =mid ^ 2-a[i].y^2<0,说明当前的a[i].y的长度大于mid,说明mid取小了;然后再找当前点距离:首先用L、R来维护一段当前点x的范围,然后缩短这个范围,如果超过这个范围,说明最大距离变大了。如果在循环过程中,没有出现上述两种情况,舍弃右部。
//三分
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=100005;
struct node{
int x,y;
};
int n;
node a[maxn];
double check(double x)
{
double max=0;
for (int i=1;i<=n;i++)
{
double tmp=sqrt(a[i].y*a[i].y+(a[i].x-x)*(a[i].x-x));
if (tmp>max) max=tmp;
}
return max;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
double l=-100000,r=100000;
double mid,midm; //三分的精髓,将选取的两个中间值进行比较,看看谁是
for(int i=0;i<100;i++){
mid=l+(r-l)/2; //最中间的
midm=mid+(r-mid)/2;//右部中间值
if(check(mid)>check(midm)) //极大值
l=mid;
else
r=midm;
}
printf("%.4lf\n",check(mid));
return 0;
}
//二分
#include<bits/stdc++.h>
using namespace std;
struct node{
double x;
double y;
};
node a[200005];
const double minn=1e-9;
int n;
bool check(double mid){
double L=-1000000000,R=1000000000;
for(int i=0;i<n;i++){
if(mid*mid-a[i].y*a[i].y<0)
{
return 0;
}
double l=-sqrt((mid*mid-a[i].y*a[i].y))+a[i].x;
double r=sqrt((mid*mid-a[i].y*a[i].y))+a[i].x;
if(L>r||R<l){
return 0;
}
L=max(l,L); R=min(r,R);
}
return 1;
}
int main(){
double l,r,ans;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lf %lf",&a[i].x,&a[i].y);
}
l=0,r=50000;
while(l+minn<r){
double mid=(l+r)/2;
if(check(mid)){
r=ans=mid;
}
else l=mid;
}
printf("%.4lf\n",ans);
return 0;
}
D 牛牛与牛妹的约会
这道题难度低于上一道。有两种情况,判断一下:在最后一步之前(1单位之前,因为1的立方根是他本身),走闪现距离牛妹近,还是乖乖走单位一距离牛妹近:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const double pi=1.0/3.0;
ll n;
ll a,b;
int main(){
scanf("%lld",&n);
while(n--){
scanf("%lld%lld",&a,&b);
double ans=0;
double nn=a;
while(1){
double nu1,nu2;
nu1=abs(nn-b);
if(a>0)
nu2=pow(nn,pi);
else
nu2=-pow(-nn,pi);
if(abs(nu2-b)+1.0<nu1){ //距离大于1,闪现更快
nn=nu2;ans+=1.0;
}
else{//按速度单位1/s走
ans+=nu1;break;
}
}
printf("%.9f\n",ans);
}
}
E enjoy the game
这一题,很显然,奇数肯定Bob赢,偶数一个一个的找,2找不到,4也找不到Bob必赢的方法,6可以,8不行,10可以,12可以,16不行…
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e3+10;
int main()
{
ll n;
cin>>n;
ll i=2;
while(i<=n){
if(i==n){
printf("Alice\n");
return 0;
}
else i*=2;
}
printf("Bob\n");
return 0;
}
F 碎碎念
这一题也是找规律,不难,找完规律后会发现是前缀和
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1000000007;
ll t,n;
ll a[100005];
ll b[100004];
int main(){
cin>>t>>n;
for(int i=0;i<t;i++){
a[i]=1;
}
a[t]=2;
for(int i=t+1;i<=100000;i++){
a[i]=a[i-1]+a[i-t-1];
a[i]%=mod;
}
b[0]=0;
for(int i=1;i<=100000;i++){//前缀和
b[i]=b[i-1]+a[i];
b[i]%=mod;
}
while(n--){
ll x,y;
cin>>x>>y;
ll sum=0;
sum=(b[y]-b[x-1]+mod)%mod;
cout<<sum<<endl;
}
return 0;
}
H Hash
要找到比原来的字符串数字大的,又要前后的哈希值相等,分析前面的代码发现,所谓的哈希值,就是将字符串转换为26进制的数字,只要将前面的数字+mod,再转码为字符串就行了,关键在于,不要超过26*6-1.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll mod;
char a[7];
char b[7];
int main(){
while(scanf("%s%lld",a,&mod)!=EOF){
ll num=0;
for(int i=0;i<6;i++){
num=num*26+a[i]-'a'; //将字符型数组改成26进制的数字;
}
num+=mod; //保证找到字典序最小且大于s
for(int i=5;i>=0;i--){ //转码,将26进制转换成字符型数组
b[i]=num%26+'a';
num/=26;
}
if(num)//所有字母>z,不满足题意
printf("-1\n");
else
printf("%s\n",b);
}
}
I I题是个签到题
有小坑,只要注意 100 100 40 30和100 100 100 40就可以了,因为他算上重复的。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e3+10;
struct node{
int lo;
int num;
};
node a[maxn];
bool comparison(node a,node b){
return a.num>=b.num;
}
int main()
{
int m,n;
cin>>m>>n;
for(int i=0;i<m;i++){
cin>>a[i].num;
a[i].lo=i;
}
sort(a,a+m,comparison);
/*for(int i=0;i<m;i++){
printf("---%d:%d---",a[i].lo,a[i].num);
}*/
int mm=1,m1=0;
for(int i=1;i<m-1;i++){
mm++;
if(mm>=3&&a[i].num!=a[i+1].num){
m1=i;
break;
}
}
for(int i=0;i<=m1;i++){
if(a[i].lo==8){
printf("Yes\n");
// printf("111");
return 0;
}
}
//printf("\n");
int ma=8*n;
int aa=0;
for(int i=0;i<m;i++){
if(a[i].lo==8){
aa=i;break;
}
}
// printf("++%d:%d++\n",a[aa].lo,a[aa].num);
int mb=a[aa].num*10;
if(ma<=mb){
printf("Yes\n");
return 0;
}
printf("No\n");
return 0;
}
J 牛牛战队的秀场
首先要求出,半径为r的正n边形的外切圆,其圆内的正n边形的边长的计算公式:2rsin(pi/n),然后找出ii到jj最短要走几条边:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PI 3.1415926
const int maxn=1e3+10;
int main()
{
int n;
ll r,ii,jj;
scanf("%d%lld%lld%lld",&n,&r,&ii,&jj);
double ie;
ie=2*r*sin(PI/(n*1.0));
//printf("%.6f\n",ie);
int nu=0;
int maxnu=n/2;
int in=max(ii,jj);
int jn=min(ii,jj);
//printf("%d %d",in,jn);
if((in-jn)<=maxnu)
nu=in-jn;
else
nu=(jn+n-in);
double ans=ie*(nu*1.0);
printf("%.6f\n",ans);
return 0;
}