2018-2019赛季多校联合新生训练赛第四场(2018/12/9)补题题解

感慨

这次难度有了明显的上升啊。。。中间一些题也是挺贱的

A 数一数(思维)

实际上根据观察一个奇数对应一个偶数是一张正反面,那么给定两个区间是不是可以直接枚举呢?

解法

①枚举,如果中间的数有等于偶数的那么页数加一

②输出,如果第一页是奇数那么页数再加一否则直接输出

代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,m,sum=0;
  cin>>n>>m;
  for(int i=n;i<=m;i++)
  if(i%2==0)
  sum++;
  if(n%2==0)
  cout<<sum;
  else
  cout<<sum+1;
}

B 博物馆(语法基础)

这个题边输入边输出即可

代码

#include <bits/stdc++.h>
using namespace std;
map<int,int> num;
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,m,re=0,p=1;
  cin>>n;
  for(int i=0;i<n;i++)
  {
    int t;
    cin>>t;
    if(t==0)
    {
      int t1;
      cin>>t1;
      num[p++]=t1+1;
      re+=t1+1;
    }
    if(t==1)
    {
      int t1;
      cin>>t1;
      re-=num[t1];
    }
  }
  cout<<re;
}

C 旅游(基础编程能力)

把每个区间的断开点,也就是拥挤度大于k的下标找出来,枚举每一种情况然后输出最大值即可

代码

#include <bits/stdc++.h>
using namespace std;
int bk[100005],num[100005];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,k,p=1,re=-1;
  cin>>n>>k;
  for(int i=1;i<=n;i++)
  {
    int t1;
    cin>>t1;
    if(t1>k)
    bk[p++]=i;
  }
  for(int i=1;i<=p;i++)
  {
    if(i==p)
    num[i]=n-bk[i-1],re=max(re,num[i]);
    else
    num[i]=bk[i]-bk[i-1]-1,re=max(re,num[i]);
  }
  cout<<re;
}

D 17倍(字符串模拟)

这个题还是有点繁琐的,实际上就是大数加法的一个变形

解法

①注意到最终有1000位,所以说直接字符串模拟走起

②说是乘以17实际上相加16次即可(当时我因为加了17次一直怀疑我打的有问题。。。)

③模拟一下进位,等情况。如果位数不同还得补0

怎么模拟二进制加法?

①翻转字符串,因为我们要从低位开始加,所以要翻转字符串

②比较两个加数是不是相同的位数,如果位数不相同,那么需要把位数少的后面加0(在第一步翻转的基础上)

③模拟进位

(1)当前位的数字数的计算公式是 n=a[i]+b[i]-'0'-'0'+jw now=n%2;

(2)jw=n/2

(3)最后如果还有进位那么还得在加上一个1即可

代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  string a;
  cin>>a;
  reverse(a.begin(),a.end());
  string ans=a,b=a;
  for(int k=0;k<16;k++)
  {
    int rel=0;
    int jw=0;
    string t="";
    a=b;
    int ll=a.size();
    for(int i=0;i<ans.size()-ll;i++)
    a+='0';
    for(int i=0;i<ans.size();i++)
    {
      int now=ans[i]+a[i]-'0'-'0'+jw;
      jw=now/2;
      now%=2;
      t+=char(now+'0');
    }
    if(jw>0)
    t+=char(jw+'0');
    ans=t;
  }
  reverse(ans.begin(),ans.end());
  cout<<ans;
}

python版本(比赛禁用)

print(bin(int(input(),2)*17)[2:])

E 约数国王

待填坑

F 移动石子(博弈论)

实际上这个题根本不用什么NP计算啊什么的,直接把这个正方形看成一条直线然后找一下什么情况下他们最终拿不到

显然n*n为偶数kakashi赢否则就输

代码

#include <bits/stdc++.h>
using namespace std;
int bk[100005],num[100005];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n;
  while(cin>>n&&n)
  {
    int t=n*n;
    if(t%2==0)
    cout<<"Kakashi\n";
    else
    cout<<"Lost\n";
  }
}

G 列车线路

待填坑

H 搭积木

待填坑

I 幸运数字III(数论)

这个题要用long long!!!

具体做法是直接分两步暴力求解即可

代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  long long n;
  cin>>n;
  long long t1=n,t2=n,ans1=0,ans2=0;
  while(1)
  {
    if(t1%4==0)
    {
      ans1++;
      t1/=4;
    }
    else
    break;
  }
  while(1)
  {
    if(t2%7==0)
    {
      ans2++;
      t2/=7;
    }
    else
    break;
  }
  cout<<ans1<<" "<<ans2;
}

J 英雄卡(基础编程能力)

这个题我沙雕的用了等差中项的两倍等于左右两项之和的这个式子,后来发现连续的意思是从左到右相差都是一

这个题的坑点在于可能有很多重复的卡比如 1 1 2 2 3 3这样直接排序扫遍一遍肯定是不行的,我们还需要在一个节点后找比他大的一个数,再在这个数找比他还大的数看看是不是满足条件

并且还得打标记,把用过的卡标记上,避免重复使用

代码

#include <bits/stdc++.h>
using namespace std;
int num[1000005];
int bk[1000005];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,sum=0;
  cin>>n;
  for(int i=0;i<n;i++)
  cin>>num[i];
  sort(num,num+n);
  for(int i=0;i<n;i++)
  {
    if(bk[i])
    continue;
    int t2,t3,id2,id3;
    for(int j=i+1;j<n;j++)
    if(num[j]>num[i]&&!bk[j])
    {
      t2=num[j];
      id2=j;
      break;
    }
    for(int j=i+1;j<n;j++)
    if(num[j]>t2&&!bk[j])
    {
      t3=num[j];
      id3=j;
      break;
    }
    if(t2-num[i]==1&&t3-t2==1&&!bk[i]&&!bk[id2]&&!bk[id3])
    {
      bk[i]=bk[id2]=bk[id3]=1;
      sum++;
    }
}
    cout<<sum;
  }

K 最强阵容(字符串基础)

本来是紫书原题,但是数据量有点大直接T,那么就需要观察一下规律了

实际上要想让字符串的字典序最小,那么第一个字符必须保证最小吧,要不怎么让字典序最小呢?

这样我们把第一个最小的字符的位置找出来,然后去比较这些字符组成的串的字典序,那么能直接降低复杂度了

代码

#include <bits/stdc++.h>
using namespace std;
int num[30005];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,mk=99999,id;
  cin>>n;
  string a="";
  for(int i=0;i<n;i++)
  {
    char c;
    cin>>c;
    mk=min(mk,int(c));
    a+=c;
  }
  int p=0;
  for(int i=0;i<a.size();i++)
  {
    if(a[i]==mk)
    num[p++]=i;
  }
  int len=a.size();
  a=a+a;
  string minn=a;
  for(int i=0;i<p;i++)
  {
    string t="";
    for(int j=num[i];j<num[i]+len;j++)
    t+=a[j];
    if(t<minn)
    {
      minn=t;
      id=num[i]+1;
    }
  }
  cout<<id;
}

L 最强素数

待填坑

posted @ 2018-12-09 20:07  baccano!  阅读(396)  评论(0编辑  收藏  举报