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

2018-2019賽季多校聯合新生訓練賽第五場(2018/12/14)補題題解

A 【字串】ISBN號碼(字串基礎)

字串基礎題,注意一下x的特判即可

程式碼

#include <bits/stdc++.h>
using namespace std;
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  string a;
  int p=1,sum=0;
  cin>>a;
  for(int i=0;i<a.size()-1;i++)
  if(isdigit(a[i]))
  sum+=(a[i]-'0')*p++;
  sum%=11;
  if(sum==10)
  {
    if(a[a.size()-1]=='X')
    cout<<"Right";
    else
    {
      for(int i=0;i<a.size()-1;i++)
      cout<<a[i];
      cout<<'X';
    }
  }
  else
  {
    if(char(sum+'0')==a[a.size()-1])
    cout<<"Right";
    else
    {
      for(int i=0;i<a.size()-1;i++)
      cout<<a[i];
      cout<<char(sum+'0');
    }
  }
 
}

B 第N個智慧數(數學)

打表題

解法

把所有的平方差都列舉一下

for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
cout<<i*i-j*j;

這樣還會出現重複的項,並且還是亂序的,我是打出表來之後再把他們放到set中進行進行去重與排序然後輸出即可

程式碼

#include <bits/stdc++.h>
using namespace std;
int bk[]={這裡是打表};
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    set<int> st;
    for(int i=0;i<4950;i++)
    st.insert(bk[i]);
    int n,sum=0;
    cin>>n;
    for(auto it=st.begin();it!=st.end();it++)
    {
        sum++;
        if(sum==n)
        {
            cout<<*it;
            break;
        }
    }
}

C 第m大的身份證號碼(字串基礎)

這個把他們用個sort排序一下就可以了

程式碼

#include <bits/stdc++.h>
using namespace std;
string num[1666],num1[666];
bool cmp(string a,string b)
{
  string t1="",t2="";
  for(int i=6;i<=13;i++)
  t1+=a[i];
  for(int i=6;i<=13;i++)
  t2+=b[i];
  return t1<t2;
}
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,k;
  cin>>n>>k;
  for(int i=0;i<n;i++)
  cin>>num[i];
  sort(num,num+n,cmp);
  cout<<num[k-1];
}

D 鋸木棍(模擬)

這個題直接模擬即可

解法

因為塗色,所以我們可以把這個木塊當一個桶,塗色等於桶上的點放入了東西。因為塗兩種顏色且兩種顏色都是長度的約數,因此我們可以直接進行掃描

第一遍掃描掃最大值

第二遍掃描掃等於最大值的數量

程式碼

#include <bits/stdc++.h>
using namespace std;
int bk[100015];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int l,m,n,maxn=-1,sum=0,ans=0;
    cin>>l>>m>>n;
    int s1=l/m;
    int s2=l/n;
    for(int i=1;i<=l;i++)
    if(i%s1==0)
    bk[i]=1;
    for(int i=1;i<=l;i++)
    if(i%s2==0)
    bk[i]=1;
    for(int i=1;i<=l;i++)
    {
      if(bk[i]==0)
      sum++;
      else
      {
        sum++;
        maxn=max(maxn,sum);
        sum=0;
      }
    }
    for(int i=1;i<=l;i++)
    {
      if(bk[i]==0)
      sum++;
      else
      {
        sum++;
        if(sum==maxn)
        ans++;
        sum=0;
      }
    }
    cout<<maxn<<" "<<ans;
}

E 座標統計(基礎程式設計能力)

直接放入然後掃描比較即可

程式碼

#include <bits/stdc++.h>
using namespace std;
struct node
{
  int x,y;
}zb[10000];
int sum[10000];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,maxn=-1,id;
  cin>>n;
  for(int i=0;i<n;i++)
  cin>>zb[i].x>>zb[i].y;
  for(int i=0;i<n;i++)
  for(int j=0;j<n;j++)
  if(zb[j].x<zb[i].x&&zb[j].y<zb[i].y)
  sum[i]++;
  for(int i=0;i<n;i++)
  {
    if(sum[i]>=maxn)
    {
      maxn=sum[i];
      id=i+1;
    }
    cout<<sum[i]<<"\n";
  }
  cout<<id;
}

F 列印月曆(基礎程式設計能力)

可能這個題分到基礎程式設計能力有點感覺不大合適,但是這個題確實沒有別的什麼難的知識點只是需要注意一些地方

解法

①首先就是這個閏年的問題,閏年的2月還平年的2月是不一樣的

②然後是計算這月距離第一個月的第一天有幾天

③然後推出這個月的第一天是在星期幾

int t=(sum)%7;
  int day=(n+t-1)%7+1;

其中day變數就是星期幾

④之後再算出這個月具體多少天,這個還得分閏年和平年

⑤然後按照1到這個月的天數輸出即可(這裡之前還要把那些空格打印出來)

⑥注意第一行一定沒有空行要不格式錯誤(測試資料 2015 2 4)

⑦還有數字用%-4d

程式碼

#include <bits/stdc++.h>
using namespace std;
int month[]={0,31,0,31,30,31,30,31,31,30,31,30,31};
int main()
{
  /*ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);*/
  int y,m,n,yn;
  cin>>y>>m>>n;
  cout<<"S   M   T   W   T   F   S\n";
  if(y%4==0&&y%100!=0||y%400==0)
  yn=1;
  else
  yn=0;
  int c=m-1,mth,sum=0;
  for(int i=1;i<c+1;i++)
  {
    if(i==2)
    {
      if(yn)
      sum+=29;
      else
      sum+=28;
    }
    sum+=month[i];
  }
  int t=(sum)%7;
  int day=(n+t-1)%7+1;
  for(int i=0;i<(day%7)*4;i++)
  cout<<" ";
  if(m==2)
  {
    if(yn)
    mth=29;
    else
    mth=28;
  }
  else
  mth=month[m];
  int ft=1;
  for(int i=1;i<=mth;i++)
  {
    if(day==7)
    {
      if(!ft)
      cout<<"\n";
      day=0;
    }
    printf("%-4d",i);
    day++;
    ft=0;
  }
}

G 分割繩子(二分查詢)

這個地方比賽的時候,都已經做出來了,就是因為二分查詢帶小數的東西有些細節不會找,導致的出現了問題

對於小數點的精度問題,我們不能單純的用l<=r而是用帶精度的

這個題我們要精確到小數點後兩位,那麼我們可以用

while(l<=r-0.001)
//do something

其中mid也是double的,之前l=mid+1也變成了l=mid+0.001 r也相同的道理

這個題原題應該沒有什麼問題吧,裸二分查詢

判斷函式也是判斷一下當前mid值能分割出幾個繩子即可

程式碼

#include <bits/stdc++.h>
using namespace std;
double num[1005];
int n,k;
int isok(double m)
{
  int sum=0;
  for(int i=0;i<n;i++)
  sum+=num[i]/m;
  return sum>=k;
}
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  double l=0,r;
  cin>>n>>k;
  for(int i=0;i<n;i++)
  cin>>num[i],r=max(r,num[i]);
  while(l<=r-0.001)
  {
    double mid=(l+r)/2;
    if(isok(mid))
    l=mid+0.001;
    else
    r=mid-0.001;
  }
  printf("%.2f",l-0.001);
}

H 換座位(語法基礎)

排序一次跟原來比較一下看哪裡不一樣了

程式碼

#include <bits/stdc++.h>
using namespace std;
int num[666],num1[666];
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],num1[i]=num[i];
  sort(num,num+n);
  for(int i=0;i<n;i++)
  if(num[i]!=num1[i])
  sum++;
  cout<<sum;
}

I 找M進位制數(字串基礎)

這個題我還因為細節問題罰時兩次

需要注意的細節

①十進位制以下是否出現了字母或者大於等於當前進位制的數

②十進位制以上是否出現了大於等於當前進位制的字母

③第一位數字是否為0(聽說這個資料中好像沒有給出)、

程式碼

#include <bits/stdc++.h>
using namespace std;
struct node
{
  int x,y;
}zb[10000];
int sum[10000];
string st[100005];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,maxn=-1,id;
  cin>>n>>id;
  int ans=n;
  for(int i=0;i<n;i++)
  cin>>st[i];
  for(int i=0;i<n;i++)
  for(int j=0;j<st[i].size();j++)
  {
    if(st[i][0]=='0')
    {
      ans--;
      break;
    }
    if(id<=10)
    {
      if(isalpha(st[i][j]))
      {
        ans--;
        break;
      }
      if(isdigit(st[i][j]))
      {
        if(st[i][j]-'0'>id-1)
        {
          ans--;
          break;
        }
      }
    }
    if(id>10)
    {
      if(isalpha(st[i][j]))
      {
        if(st[i][j]>'A'+id-11)
        {
          ans--;
          break;
        }
      }
    }
  }
  cout<<ans;
}

J 迴圈小數(字串模擬)

這個題並不難啊,比起紫書上那個90年代的acm世界決賽的真題來說還是太嫩了點

解法

①找出迴圈節前的小數

②找出迴圈節

③把迴圈節迴圈多次加到迴圈節前的小數後面(這裡一定要比給定的要找的位數要多)

④按照要求輸出即可

程式碼

#include <bits/stdc++.h>
using namespace std;
int bk[100015];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n,f=0,ff=0;
    cin>>n;
    string a,nu="",xh="";
    cin>>a;
    for(int i=0;i<a.size();i++)
    {
      if(a[i]=='.')
      f=1;
      if(a[i]=='(')
      ff=1;
      if(f&&!ff)
      {
          if(isdigit(a[i]))
          nu+=a[i];
      }
      if(f&&ff)
      {
        if(isdigit(a[i]))
        xh+=a[i];
      }
    }
    for(int i=0;i<100005;i++)
    nu+=xh;
    cout<<nu[n-1];
}

K 單純質因數(數論)

待填坑我這個玩意-6都還不知道錯在哪裡,感覺寫對了啊

L 安裝飲水機(目前不明)

待填坑

M 分木塊(語法基礎)

程式碼

#include <bits/stdc++.h>
using namespace std;
int num[666],num1[666];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,sum=0,r1=0,r2=0,r3=0;
  cin>>n;
  for(int i=0;i<n;i++)
  {
    int t,ans1=0,ans2=0,ans3=0;
    cin>>t;
    ans1+=t/100;
    t%=100;
    ans2+=t/10;
    t%=10;
    ans3+=t;
    r1+=ans1;
    r2+=ans2;
    r3+=ans3;
  }
  cout<<r1<<"\n"<<r2<<"\n"<<r3;
}

N 活動人數(語法基礎)

程式碼

#include <bits/stdc++.h>
using namespace std;
int num[1666],num1[666];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,sum=0,r1=0,r2=0,r3=0,l,k;
  cin>>n>>l>>k;
  for(int i=0;i<n;i++)
  cin>>num[i];
  sort(num,num+n);
    for(int i=0;i<n;i++)
    if(1)
    {
      if(l>=num[i])
      {
        sum++;
        l+=k;
      }
    }
    cout<<sum;
}