1. 程式人生 > >2018-2019賽季多校聯合新生訓練賽第三場(2018/12/8)補題題解

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)

回溯

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;
}