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

感慨

这次B题实在是太沙雕了。。。。

A 朋友(思维)

这个可跟上回的传话游戏不是一个东西,这个直接找人名出现最多的次数即可。但是还要判断重复的关系,就是这个地方我把50%数据不用判断看成了100%罚时一次。与一血差了5s。。。

解法

发挥STL map的强大功能即可

代码

#include <bits/stdc++.h>
using namespace std;
map<string,int> bk;
map<string,map<string,int> > mp;
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,m,maxn=-1;
  cin>>n>>m;
  while(m--)
  {
    string a,b;
    cin>>a>>b;
    if(!mp[a][b]&&!mp[b][a])
    {
      mp[a][b]=mp[b][a]=1;
      bk[a]++;bk[b]++;
    }
    maxn=max(maxn,bk[a]);
    maxn=max(maxn,bk[b]);
  }
  cout<<maxn;
}

B 排队IV(结构体排序)

真实蠢得一批的题目。题目中有编号反而不用却用进队的顺序????白白罚时好多次还看不懂题。这出题人太沙雕了

解法

分三步排序即可。开四个vector v1,v2,v3,v4 v1装小孩 v2装中年人 v3装老年人。然后定义三个排序拍一下再按照v1 v3 v2的顺序放入v4最后输出v4即可

再说一遍这个题的编号没有任何任何的用处!!!需要在结构体中再定义一个入队顺序的变量

代码

#include <bits/stdc++.h>
using namespace std;
struct node
{
  int id,year,tm;
}num[300005];
bool cmp0(node a,node b)
{
  return a.year<b.year;
}
bool cmp1(node a,node b)
{
  return a.year==b.year?a.tm<b.tm:a.year<b.year;
}
bool cmp2(node a,node b)
{
  return a.tm<b.tm;
}
bool cmp3(node a,node b)
{
  return a.year==b.year?a.tm<b.tm:a.year>b.year;
}
deque<node> v1,v2,v3,v4;
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin>>n;
  for(int i=0;i<n;i++)
  cin>>num[i].id>>num[i].year,num[i].tm=i;
  //sort(num,num+n,cmp0);
  for(int i=0;i<n;i++)
  {
    if(num[i].year<=6)
    v1.push_back((node){num[i].id,num[i].year,num[i].tm});
    else if(num[i].year>6&&num[i].year<60)
    v2.push_back((node){num[i].id,num[i].year,num[i].tm});
    else if(num[i].year>=60)
    v3.push_back((node){num[i].id,num[i].year,num[i].tm});
  }
  sort(v1.begin(),v1.end(),cmp1);
  sort(v2.begin(),v2.end(),cmp2);
  sort(v3.begin(),v3.end(),cmp3);
  for(int i=0;i<v1.size();i++)
  v4.push_back(v1[i]);
  for(int i=0;i<v3.size();i++)
  v4.push_back(v3[i]);
  for(int i=0;i<v2.size();i++)
  v4.push_back(v2[i]);
  for(int i=0;i<v4.size();i++)
  cout<<v4[i].id<<"\n";
}

C 爱好数学的国王(数论)

这个题实际上是找最大的质因数

但是这个题跟之前的做过的题不一样,之前那个洛谷入门难度的题是两个质因数相乘得出来的数,所以那个题从小到大枚举,只要有一个变量能够使这个数整除即可

但是这个题不是,因为这个题的数是任意的

那么怎么样会输出0呢?

①n=1的时候,1不是质数直接输出0

②n不包含质因数的时候

那么怎么做?

直接把所有的因数找出来,升序排序,找到最大的质因数输出n/p(这个数),如果没有这个数输出0

代码

#include <bits/stdc++.h>
using namespace std;
int ip(int n)
{
  for(int i=2;i*i<=n;i++)
  if(n%i==0)
  return 0;
  return 1;
}
int num[20000000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int t;
  cin>>t;
  while(t--)
  {
    int n;
    cin>>n;
    if(n==1)
    cout<<0<<"\n";
    else if(ip(n))
    cout<<1<<"\n";
    else
    {
      int p=0,f=0;
      for(int i=2;i*i<=n;i++)
      if(n%i==0)
      num[p++]=i,num[p++]=n/i;
      sort(num,num+p);
      for(int i=p-1;i>=0;i--)
      {
        if(ip(num[i]))
        {
          f=1;
          cout<<n/num[i]<<"\n";
          break;
        }
      }
      if(!f)
      cout<<0<<"\n";
    }
  }
}

D 修建高楼(思维)

本来高楼就没有重复的,并且一定要按照原来的顺序去输出

那么我们可以用两个for判断一下当前遍历的这两个数中间是不是夹着一个适合的楼即可

代码

#include <bits/stdc++.h>
using namespace std;
int bk[3000],num[3000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int t,n,id,maxn=-1,ans;
  cin>>t>>n;
  for(int k=1;k<=t;k++)
  {
    for(int i=0;i<n;i++)
    cin>>num[i];
    ans=0;
    for(int i=0;i<n-1;i++)
    {
      memset(bk,0,sizeof(bk));
      for(int j=i+1;j<n;j++)
      {
        if((num[i]+num[j])%2==0&&bk[(num[i]+num[j])/2])
        ans++;
        bk[num[j]]=1;
      }
    }
    if(ans>maxn)
    {
      maxn=ans;
      id=k;
    }
  }
  cout<<id<<" "<<maxn;
}

E 金子数(结构体排序)

签到题。。。实际上把每回的金子找出来加一下排序即可

代码

#include <bits/stdc++.h>
using namespace std;
struct node
{
  long long id,sum;
}num[105];
bool cmp(node a,node b)
{
  return a.sum>b.sum;
}
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,m;
  cin>>n>>m;
  for(int i=0;i<n;i++)
  {
    long long re=0;
    for(int j=0;j<m;j++)
    {
      int t;
      cin>>t;
      if(t%8==0)
      re+=t;
    }
    num[i].id=i+1;
    num[i].sum=re;
  }
  sort(num,num+n,cmp);
  cout<<num[0].id;
}

F 扑克牌游戏(字符串基础)

注意输入的时候可能会有A J Q K

解法

边输入边加目前有的牌,再贪心把最大的那一张*m加上原来的答案即可

代码

#include <bits/stdc++.h>
using namespace std;
int num[1000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  for(int i=1;i<=13;i++)
  cin>>num[i];
  int n,m,re=0;
  cin>>n>>m;
  string a;
  cin>>a;
  for(int i=0;i<a.size();i++)
  {
    if(a[i]>'1'&&a[i]<='9')
    re+=num[a[i]-'0'];
    else if(a[i]=='1')
    re+=num[10];
    else if(a[i]=='A')
    re+=num[1];
    else if(a[i]=='J')
    re+=num[11];
    else if(a[i]=='Q')
    re+=num[12];
    else if(a[i]=='K')
    re+=num[13];
  }
  sort(num+1,num+14);
  re+=num[13]*m;
  cout<<re;
}

G 垃圾装袋(贪心)

昨天刚刚在贪心课的基础贪心题目中讲了跟这个一样的题。。。不明白的可以再去看课件。。。

代码

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

H 组装玩具(二分查找)

我一直以为这个题是每个材料都能装玩具,原来是每个材料合起来才能装玩具。。。

首先这种题目暴力肯定不行,又求最大值,可以想到用二分查找

怎么二分查找?

①首先确定一个界限,这里l是0比较明显,r是多少呢?

r可以为了保险起见,我们设置一个小一点的值,可以设置为需要最多的材料用已有的这种材料加上万能材料总共可以做几个。因为每个材料都要用上,那么可以先把万能材料都用到最多的上面,如果可以的话,这个其实就是r了

②isok函数的编写

怎么样才算ok?就是判断万能材料,因为已有的材料是固定的,只有万能材料才可以灵活的使用,所以说判断万能材料是不是够用,够用那么向上查找,否则向下查找

怎么算万能的材料是否够用?

用当前二分的玩具的个数去寻找需要的材料再与当前材料的差值就是万能材料需要补上多少

③注意中间要用long long!!!!!

代码

#include <bits/stdc++.h>
using namespace std;
long long x[100005],y[100005];
long long n,m,r;
int isok(int jk)
{
  long long sum=m;
  for(int i=0;i<n;i++)
  if(y[i]*jk>x[i])
  sum-=y[i]*jk-x[i];
  if(sum>=0)
  return 1;
  else
  return 0;
}
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin>>n>>m;
  for(int i=0;i<n;i++)
  cin>>x[i];
  for(int i=0;i<n;i++)
  {
    cin>>y[i];
    if(i==0)
    r=(x[i]+m)/y[i];
    else
    r=min(r,(x[i]+m)/y[i]);
  }
  long long l=0,ans;
  r++;
  while(l<=r)
  {
    int mid=(l+r)/2;
    if(isok(mid))
    l=mid+1;
    else
    r=mid-1;
  }
  cout<<l-1;
}

I 判奇偶(语法基础)

代码

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

J 零花钱(语法基础)

代码

#include <bits/stdc++.h>
using namespace std;
int h[1000000],w[1000000],bk[1000000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,f=0,sum=0;
  cin>>n;
  for(int i=0;i<5;i++)
  {
    int t;
    cin>>t;
    sum+=t;
    if(sum>=n)
    f=1;
  }
  if(!f)
  cout<<n-sum;
  else
  cout<<0;
}

K 统计数字(语法基础)

代码

#include <bits/stdc++.h>
using namespace std;
int h[1000000],w[1000000],bk[1000000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,sum1=0,re1=0,sum2=0,re2=0;
  cin>>n;
  for(int i=0;i<n;i++)
  {
    int t;
    cin>>t;
    if(t>0)
    {
      sum1++;
      re1+=t;
    }
    else if(t<0)
    {
      sum2++;
      re2+=t;
    }
  }
  cout<<sum1<<" "<<re1<<endl<<sum2<<" "<<re2;
}

L 译码程序(字符串基础)

这里注意.不一定在行末可能在一行的中间,我因为没有判断.还罚时了一次

代码

#include <bits/stdc++.h>
using namespace std;
int h[1000000],w[1000000],bk[1000000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  string a;
  getline(cin,a);
  for(int i=0;i<a.size();i++)
  {
    if(isalpha(a[i]))
    cout<<a[i]-'a'+1;
    else if(isspace(a[i]))
    cout<<"#";
    else if(a[i]=='.')
    break;
  }
}
posted @ 2018-12-07 21:19  baccano!  阅读(283)  评论(0编辑  收藏  举报