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

感慨

得复习回溯和dfs了。。。

A 变形虫(语法基础)

代码

#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;
  cin>>n>>m;
  for(int i=0;i<m;i++)
  cin>>num[i];
  for(int i=0;i<m;i++)
  if(num[i]==n)
  n+=num[i];
  cout<<n;
}

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,t=0,sum=0,re=0;
  cin>>n>>m;
  for(int i=0;i<m;i++)
  cin>>num[i],re+=num[i];
  sum+=m*(n/re);
  n%=re;
  while(n>0)
  {
    n-=num[t];
    t++;
    t%=m;
    sum++;
  }
  cout<<sum;
}

C 进制转换 (语法基础)

我的思路是先化成十进制,再按照栈的思想化成各种进制。。。这估计也不是正解

代码

#include <bits/stdc++.h>
using namespace std;
map<int,int> sum;
stack <char> st;
int qb(int a,int b)
{
  int re=1;
  for(int i=0;i<b;i++)
  re*=a;
  return re;
}
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,sum=0;
  cin>>n;
  string a;
  cin>>a;
  int len=a.size();
  for(int i=0;i<len;i++)
  {
    if(a[i]=='A')
    sum+=10*qb(n,len-i-1);
    else if(a[i]=='B')
    sum+=11*qb(n,len-i-1);
    else if(a[i]=='C')
    sum+=12*qb(n,len-i-1);
    else if(a[i]=='D')
    sum+=13*qb(n,len-i-1);
    else if(a[i]=='E')
    sum+=14*qb(n,len-i-1);
    else if(a[i]=='F')
    sum+=15*qb(n,len-i-1);
    else
    sum+=(a[i]-'0')*qb(n,len-i-1);
  }
  int m;
  cin>>m;
  while(sum)
  {
    int t=sum%m;
    char c;
    if(t==10)
    c='A';
    else if(t==11)
    c='B';
    else if(t==12)
    c='C';
    else if(t==12)
    c='C';
    else if(t==13)
    c='D';
    else if(t==14)
    c='E';
    else if(t==15)
    c='F';
    else if(t<10)
    c=char(t+'0');
    sum/=m;
    st.push(c);
  }
  while(st.size())
  {
    cout<<st.top();
    st.pop();
  }
}

D 最大的数II (数学)

找一下递推式,判断一下条件即可

代码

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

E 取数排列 (全排列)

打个全排列抽一下数即可

代码

#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=0;i<n;i++)
  bk[i]=i+1;
  do {
    sum++;
    if(sum==m)
    {
      for(int i=0;i<n;i++)
      {
        cout<<bk[i];
      }
      break;
    }
  } while(next_permutation(bk,bk+n));
}

F 懒羊羊找朋友 (结构体排序)

解法

首先要找距离

公式为:|xi-x|+|yi-y|

然后把所有的相同数的点的距离算出来之后,再按照他给的条件排个序输出即可

代码

#include <bits/stdc++.h>
using namespace std;
int mp[1000][1000];
struct node
{
  int x,y,dis;
}bk[1000000];
bool cmp(node a,node b)
{
  return a.dis==b.dis?a.x==b.x?a.y<b.y:a.x<b.x:a.dis<b.dis;
}
int main()
{
  /*ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);*/
  int n,m,x,y,p=0;
  cin>>n>>m>>x>>y;
  for(int i=1;i<=n;i++)
  for(int j=1;j<=m;j++)
  cin>>mp[i][j];
  for(int i=1;i<=n;i++)
  for(int j=1;j<=m;j++)
  if(mp[i][j]==mp[x][y])
  {
    if(i==x&&j==y)
    continue;
    bk[p].x=i,bk[p].y=j,bk[p++].dis=abs(i-x)+abs(j-y);
  }
  sort(bk,bk+p,cmp);
  cout<<bk[0].x<<" "<<bk[0].y;
}

G 求满足条件的数 (语法基础)

代码

#include <bits/stdc++.h>
using namespace std;
int sum[100000];
int bk[100000];
char c[10000];
int main()
{
  /*ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);*/
  int n,tot=0;
  cin>>n;
  for(int i=69;i<=n;i++)
  {
    stringstream s;
    s<<i;
    string ss;
    s>>ss;
    int sum=0;
    for(int i=0;i<ss.size();i++)
    sum+=ss[i]-'0';
    if(sum==15)
    printf("%6d",i),tot++;
    if(tot==8)
    printf("\n"),tot=0;
  }
}

H 自然数无序拆分 (DFS)

这里还需要打表才可以接受。。。如果用dfs的话。

首先我们得确定dfs中要有几个变量,sum和cur肯定是必不可少的吧。一个是总和一个是当前的进行的步骤

但是我们观察发现如果要去重的话,那么还需要保证下一位比上一位还要大,那么还需要一个记录上一位大小的变量now。剩下的就基本一目了然了

只需要枚举一下位数即可

代码(打表程序)

#include <bits/stdc++.h>
using namespace std;
int n,ans,k;
void dfs(int now,int sum,int cur)
{
  if(cur==k)
  {
    if(sum==n)
    ans++;
  }
  else
  {
    for(int i=now;sum+i*(k-cur)<=n;i++)
    dfs(i,sum+i,cur+1);
  }
}
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin>>n;
  for(int i=1;i<=n;i++)
  {
    k=i;
    dfs(1,0,0);
  }
  cout<<ans;
}

这里解释一下这个剪枝的问题,因为100过于庞大,所以一般的打表会很慢很慢,那么我们需要进行剪纸。那么我们就要计算一下如果之后的位数全是当前位数的话,答案加起来还比原先的数大,那么就没有必要再搜索了,因为搜索的之后的数一定比原来的数大,原来的数都不能满足小于n,还求别的数小于n?

I 大写字母的序列 (语法基础)

代码

#include <bits/stdc++.h>
using namespace std;
int sum[100000];
int bk[100000];
char c[10000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  for(int i=0;i<3;i++)
  cin>>sum[i];
  for(int i=0;i<3;i++)
  cin>>c[i];
  sort(sum,sum+3);
  bk['A']=sum[0];
  bk['B']=sum[1];
  bk['C']=sum[2];
  for(int i=0;i<3;i++)
  cout<<bk[c[i]]<<" ";
}

J 弗洛格 (语法基础)

代码

#include <bits/stdc++.h>
using namespace std;
int sum[100000];
int bk[100000];
char c[10000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin>>n;
  if(n<=26)
  cout<<27-n;
  else if(n>26)
  {
    n-=26;
    cout<<30-n+1;
  }
}

K 移动次数最少 (贪心)

洛谷试炼场的原题。。。原题好像是叫做移动纸牌。

解法

因为这里最左边的不能和最右边的联系。所以只有中间的那些能够左右的交换。

两个变量很麻烦,我们直接设置一个移动变量xi代表移动的卡牌数目

例如x1代表1给2的卡牌数

xi=ai-avg(ai代表当前手中的卡牌,avg代表平均最终的卡牌数)

线性扫描一下如果当前的牌经过之前的移动还不是avg的话那么答案加一次

最后输出即可

代码

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

L 小矮人 (语法基础)

代码

#include <bits/stdc++.h>
using namespace std;
int sum[100000];
int bk[100000];
char c[10000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  for(int i=0;i<6;i++)
  {
    int t;
    cin>>t;
    bk[t]++;
  }
  for(int i=1;i<=7;i++)
  if(!bk[i])
  cout<<i;
}

M 小米 (语法基础)

代码

#include <bits/stdc++.h>
using namespace std;
int sum[100000];
int bk[100000];
char c[10000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int f,m,me;
  cin>>f>>m>>me;
  if(me==1)
  cout<<(f+m+13)/2;
  else if(me==0)
  cout<<(f+m-13)/2;
}

N 小球 (思维)

直接把所有的情况拿出来做个比较即可

解法

经过观察,我们发现如果要把一个红球放到蓝箱子里那么一定需要把一个蓝球放到红箱子里

那么这里肯定只有三种情况

①红球放到红箱子,蓝球放到蓝箱子

②红球或者蓝球数量少的全部放到另一个箱子,其他的还在原来的相同颜色的箱子内

③红球蓝球数量相等全部互换

为什么不可能有部分的情况?

因为移动或者不移动肯定会有一个价值的变化,而这个变化肯定也只有变大或者变小,不可能说你移动部分之后就会比移动全部的要变化的好

代码

#include <bits/stdc++.h>
using namespace std;
int num[1000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int a,b,c,d,e;
  cin>>a>>b>>c>>d>>e;
  int r1=a*c+b*d;
  int r2;
  if(a>b)
  r2=2*b*e+(a-b)*c;
  else if(a<b)
  r2=2*a*e+(b-a)*d;
  else
  r2=2*a*e;
  cout<<max(r1,r2);
}

O 找最长良序字符串 (字符串基础)

数据太小了,直接暴力就行了

代码

#include <bits/stdc++.h>
using namespace std;
int sum[100000];
int bk[100000];
char c[10000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  string a;
  cin>>a;
  int re=-1;
  for(int i=0;i<a.size();i++)
  {
    char t=a[i];
    int sum=1;
    for(int j=i+1;j<a.size();j++)
    {
      if(a[j]>t)
      sum++,t=a[j];
      else
      break;
    }
    re=max(re,sum);
  }
  cout<<re;
}
posted @ 2018-12-08 22:52  baccano!  阅读(455)  评论(0编辑  收藏  举报