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

感慨

这次题目又有了难度明显的提升

感谢

感谢lyj大佬 lk大佬 duny大佬!!!

A 春游(贪心)

首先可以计算一下发现实际上做33的车性价比是比较高的那么我们应该能做33就做33

你可能会问我们取一个33与49的公倍数,说不定做49的更好?

但是实际上即使这样还是33的花钱少!!!

这样我们有三种可能

①人数正好是33的倍数

全部做33的车

②人数余33小于等于16

那么少一辆33的多一辆49的

③人数余33大于16

多一辆33的

最终注意如果人数小于33特判一下即可

最终我们用了O(1)的时间解决了这个问题

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
  ios::sync_with_stdio(0);
  cout.tie(0);
  cin.tie(0);
  ll n;
  cin>>n;
  ll t=n%33;
  if(n<33)
  cout<<1900;
  else if(t>0&&t<=16)
  cout<<(n/33-1)*1900+3300;
  else if(t>16)
  cout<<(n/33+1)*1900;
  else if(t==0)
  cout<<(n/33)*1900;
}

B 斗地主IV(模拟)

这个不用说了吧,都会做,模拟一下就可以了

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll num[1000];
int main()
{
  ios::sync_with_stdio(0);
  cout.tie(0);
  cin.tie(0);
  ll n;
  cin>>n;
  while(n--)
  {
    ll ps,sc,cas;
    cin>>ps>>sc>>cas;
    if(cas==1)
    {
      for(int i=1;i<=4;i++)
      if(ps==i)
      num[i]+=sc*3;
      else
      num[i]-=sc;
    }
    else if(cas==2)
    {
      for(int i=1;i<=4;i++)
      if(ps==i)
      num[i]-=sc*3;
      else
      num[i]+=sc;
    }
  }
  for(int i=1;i<=4;i++)
  cout<<num[i]<<" ";
}

C BMI(语法基础)

注意用double去比较即可,如果不是good那么for暴力求解

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll num[10000];
int main()
{
  ios::sync_with_stdio(0);
  cout.tie(0);
  cin.tie(0);
  double h,w;
  cin>>h>>w;
  h/=100;
  double t=w/pow(h,2);
  if(t>=18&&t<=24)
  cout<<"Good!";
  else
  {
    if(t>24)
    {
      cout<<"Too fat!\n";
      for(double i=w-1;i;i--)
      {
        double t1=(i)/pow(h,2);
        if(t1<=24)
        {
          cout<<w-i;
          break;
        }
      }
    }
    else if(t<18)
    {
      cout<<"Too thin!\n";
      for(double i=w+1;;i++)
      {
        double t1=(i)/pow(h,2);
        if(t1>=18)
        {
          cout<<i-w;
          break;
        }
      }
    }
  }
}

D 人工智能(模拟)

这个题四个方向的车好说,皇后不好说。。。

皇后的斜向走还需要写4个函数

我比赛的时候昏迷了用了有标记就返回,实际上完全不需要这个条件

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int bk[2333][2333],mp[2333][2333];
int n;
void dfs1(int x,int y)
{
  for(int i=x-1;i>=0;i--)
  if(mp[i][y]==0)
  bk[i][y]=1;
  else if(mp[i][y]==1||mp[i][y]==2)
  break;
  for(int i=x+1;i<n;i++)
  if(mp[i][y]==0)
  bk[i][y]=1;
  else if(mp[i][y]==1||mp[i][y]==2)
  break;
  for(int i=y-1;i>=0;i--)
  if(mp[x][i]==0)
  bk[x][i]=1;
  else if(mp[x][i]==1||mp[x][i]==2)
  break;
  for(int i=y+1;i<n;i++)
  if(mp[x][i]==0)
  bk[x][i]=1;
  else if(mp[x][i]==1||mp[x][i]==2)
  break;
}
void dfs2(int x,int y)
{
  if(x>=0&&y<n&&mp[x][y]==0)
  bk[x][y]=1,dfs2(x-1,y+1);
  else
  return;
}
void dfs3(int x,int y)
{
  if(x>=0&&y>=0&&mp[x][y]==0)
  bk[x][y]=1,dfs3(x-1,y-1);
  else
  return;
}
void dfs4(int x,int y)
{
  if(x<n&&y<n&&mp[x][y]==0)
  bk[x][y]=1,dfs4(x+1,y+1);
  else
  return;
}
void dfs5(int x,int y)
{
  if(x<n&&y>=0&&mp[x][y]==0)
  bk[x][y]=1,dfs5(x+1,y-1);
  else
  return;
}
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin>>n;
  for(int i=0;i<n;i++)
  for(int j=0;j<n;j++)
  cin>>mp[i][j];
  for(int i=0;i<n;i++)
  for(int j=0;j<n;j++)
  if(mp[i][j]==1)
  bk[i][j]=1,dfs1(i,j);
  else if(mp[i][j]==2)
  bk[i][j]=1,dfs1(i,j),dfs2(i-1,j+1),dfs3(i-1,j-1),dfs4(i+1,j+1),dfs5(i+1,j-1);
  int sum=0;
  for(int i=0;i<n;i++)
  for(int j=0;j<n;j++)
  if(!bk[i][j])
  sum++;
  cout<<sum;
}

E 基因锁(KMP)

比赛的时候有小bug,没有发现,后来询问duny大佬才发现了bug。。。。

思路就是kmp找染色的个数。然后遍历染色的部位一段一段的计算切点的个数

切点个数计算公式为

当前连续的染色个数/肥胖基因的长度

最后把切点加起来就可以了

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int nex[6666666],mk[6666666];
char a[6666666],b[6666666];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ll n,m,sum=0,re=0,ans=0;
  cin>>n>>m;
  cin>>a+1>>b+1;
  ll len1=strlen(a+1);
  ll len2=strlen(b+1);
  ll j=0,p=0;
  for(int i=2;i<=len1;i++)
  {
    while(j&&b[i]!=b[j+1])
    j=nex[j];
    if(b[i]==b[j+1])
    j++;
    nex[i]=j;
  }
  j=0;
  for(int i=1;i<=len1;i++)
  {
    while(j&&a[i]!=b[j+1])
    j=nex[j];
    if(a[i]==b[j+1])
    j++;
    if(j==len2)
    {
      for(int k=i-j+1;k<=i;k++)
      mk[k]=1;
    }
  }
  for(int i=0;i<=len1+1;i++)
  if(mk[i]==1)
  re++,ans++;
  else if(mk[i]==0)
  sum+=re/m,re=0;
  cout<<ans<<" "<<sum;
}

F 量子计算(数学)

这个题好像是高中数学竞赛的真题来着

公式

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ll n,m;
  cin>>n>>m;
  if(n%2==0)
  {
    ll t1=m-1;
    t1%=10000007;
    ll re=1;
    for(int i=0;i<n;i++)
    re*=(m-1)%10000007,re%=10000007;
    ll ans=re+t1;
    ans%=10000007;
    cout<<ans;
  }
  else
  {
    ll t1=m-1;
    t1%=10000007;
    ll re=1;
    for(int i=0;i<n;i++)
    re*=(m-1)%10000007,re%=10000007;
    ll ans=re-t1;
    ans%=10000007;
    cout<<ans;
  }
}

G 常州拔河(贪心)

就是我课件里的上船问题

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
  int sum,id;
}num[6666666];
bool cmp(node a,node b)
{
  return a.sum==b.sum?a.id<b.id:a.sum<b.sum;
}
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].sum,num[i].id=i+1;
  sort(num,num+n,cmp);
  int t=n/2;
  cout<<n/2<<" ";
  for(int i=0;i<n;i++)
  {
    cout<<num[i].id<<" ";
    t--;
    if(t==0)
    break;
    cout<<num[n-1-i].id<<" ";
    t--;
    if(t==0)
    break;
  }
}

H 常州买衣服(贪心)

既然优惠后一定价格小于等于原价,那么先对优惠后的价格进行一次排序,先买有优惠的。

再按照优惠前的排序,优惠券用光了买没有优惠的,注意不要买重了

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
  int pre,now,id;
}num1[666666],num2[666666];
int bk[666666];
ll ans;
bool cmp1(node a,node b)
{
  return a.now<b.now;
}
bool cmp2(node a,node b)
{
  return a.pre<b.pre;
}
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ll n,k,m;
  cin>>n>>k>>m;
  for(int i=0;i<n;i++)
  {
    cin>>num1[i].pre>>num1[i].now;
    num1[i].id=num2[i].id=i;
    num2[i].pre=num1[i].pre;
    num2[i].now=num1[i].now;
  }
  sort(num1,num1+n,cmp1);
  sort(num2,num2+n,cmp2);
  for(int i=0;i<k;i++)
  {
    m-=num1[i].now;
    if(m>0)
    ans++,bk[num1[i].id]=1;
    else
    break;
  }
  for(int i=0;i<n;i++)
  {
    if(!bk[num2[i].id])
    {
      m-=num2[i].pre;
      if(m>0)
      ans++,bk[num2[i].id]=1;
      else
      break;
    }
  }
  cout<<ans;
}

I Domino(递推)

老生常谈的递推例题。。。应该都做过原题吧

公式

f[i]=f[i-1]+f[i-2]

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll num[10000];
int main()
{
  ios::sync_with_stdio(0);
  cout.tie(0);
  cin.tie(0);
  num[1]=1;
  num[2]=2;
  for(int i=3;i<=1000;i++)
  num[i]=num[i-1]%1000000007+num[i-2]%1000000007,num[i]%=1000000007;
  ll n;
  cin>>n;
  cout<<num[n];
}

J Block(不明)

待填坑

K Ring(不明)

待填坑

L StringII(思维)

总共四种情况

①如果上面的字符串中的字符小于下面的那么Impossible

②如果两个字符串长度相等,且不满足①那么Alice

③如果上面的字符串比下面的字符串长,且按顺序包含下面的那么Bob

④在③的条件上如果不按顺序包含那么就是Both

代码

#include <bits/stdc++.h>
using namespace std;
int bk1[300];
int bk2[300];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  string a,b;
  int t;
  cin>>t;
  while(t--)
  {
    int f=0;
    memset(bk1,0,sizeof(bk1));
    memset(bk2,0,sizeof(bk2));
    cin>>a>>b;
    for(int i=0;i<a.size();i++)
    bk1[a[i]-'a']++;
    for(int i=0;i<b.size();i++)
    bk2[b[i]-'a']++;
    for(int i=0;i<26;i++)
    if(bk1[i]<bk2[i])
    {
      f=1;
      break;
    }
    if(f)
    {
      cout<<"Impossible\n";
      continue;
    }
    if(a.size()==b.size())
    cout<<"Alice\n";
    else
    {
      int k=0;
      for(int i=0;i<a.size();i++)
      if(a[i]==b[k])
      k++;
      if(k==b.size())
      cout<<"Bob\n";
      else
      cout<<"Both\n";
    }
  }
}
posted @ 2018-12-22 11:14  baccano!  阅读(313)  评论(0编辑  收藏  举报