第五届太原理工大学新生赛(决赛)题解

题解)

  • 第五届太原理工大学新生赛(决赛)
    • :star:A.810975
      • :star2:题意
      • :cherries:解决思路
      • :pear:代码
    • :star:B.hammer玩游戏
      • :star2:题意
      • :cherries:解决思路
      • :pear:代码
    • :star:C.Gold Rong 的数组
      • :star2:题意
      • :cherries:解决思路
      • :pear:代码
    • :star:D.勇敢鼠鼠
      • :star2:题意
      • :cherries:解决思路
      • :monkey:代码
    • :star:E.syuggie的彩票
      • :star2:题意
      • :cherries:解决思路
      • :pear:代码
    • :star:F.A hard problem
    • :star:G.An easy string problem
      • :star2:题意
      • :cherries:解决思路
      • :pear:代码
    • :star:H.An easy game
      • :star2:题意
      • :cherries:解决思路
      • :pear:代码
    • :star:I.饿饿饭饭是何意味
      • :star2:题意
      • :cherries:解决思路
      • :pear:代码
    • :star:J.TYUT链
    • :star:K.抢车位
      • 题意
      • 解决思路
      • 代码
    • :star:L.Syuggie的减肥计划
      • 题意
      • 解决思路
      • 代码
    • :star:M.公平分配
    • :star:N.A+B problem
      • :star2:题意
      • :cherries:解决思路
      • :pear:代码

第五届太原理工大学新生赛(决赛)


⭐️A.810975

第五届太原理工大学新生赛(决赛)题解_第1张图片

题意

就是说n个对战夜吹说他赢了几把,连胜了几把看有没有可能,有就输出yes+方案,没有就输出no

解决思路

分类讨论,想什么时候就是在吹。(题目保证n>=m>=k)

  1. 当k=0,一局连胜都没有,那么肯定m是0才是对的(一局都没赢,输出n个0),否则就是在吹。
  2. 当k>0:
    (1) 特判:m==k的时候(即是赢的局数和连胜的局数一样多,此时必定有解,输出m个1后输出n-m个0;
    (2)m>k的时候:如果n=m=k那么就输出n个1,否则就输出no,因为总共就n局都赢了肯定k也等于n;
    n!=m的时候我们可以这样想,两个0可以包住k个1让他与连胜k场分开,那么我们就可以采用先输出k个1,然后输出一个0在输出k个1,所以只要判断有几局没有赢就有几个0,然后判断k倍0的个数是否大于等于1的个数,这样是可以的,否则就不行。
    3.输出要注意0如果多了就后面补上就行。
    第五届太原理工大学新生赛(决赛)题解_第2张图片

代码

#include
using namespace std;
int main()
{
    int n, m, k; cin >> n >> m >> k;
    if (k == 0)
    {
        if (m == 0) {
            cout << "YES\n";
            for (int i = 0; i < n; i++)cout << 0;
        }
        else cout << "NO\n";
    }
    else
    {
        if (m == k) {
            cout << "YES\n";
            for (int i = 0; i < n; i++)
            {
                if (i < m)cout << 1; else cout << 0;
            }
        }
        else
        {
            if (n == m)
            {
                if (k != m)cout << "NO\n";
                else
                {
                    for (int i = 0; i < n; i++)cout << 1;
                }
            }
            else
            {
                int a = n - m, b = m - k;
                int c = a;int e=k;
                if (c * k >= b)
                {
                    cout << "YES\n";
                    while (k--)cout << 1;
                    while (b>0)
                    {
                        int d = e;
                        cout << 0; a--;
                        while (d--&&b>0) { cout << 1; b--; }
                    }
                    while (a--)cout << 0;
                }
                else cout << "NO\n";
            }
        }
    }
}

⭐️B.hammer玩游戏

第五届太原理工大学新生赛(决赛)题解_第3张图片

题意

其中 A 代表进攻, B 代表防御,C 代表蓄力。
如果 Hammer 可以击杀电脑,则输出一个整数,表示 Hammer 能得到的最高得分。
否则结局一定是平局,(不然 Hammer 的透视挂岂不是白买了!)输出 draw

解决思路

1.当机器人进攻时我们只能防御;
2.当机器人防御时我们可以蓄力得到高分
3.当机器人蓄力时我们可以蓄力,也可以进攻如果有能量。为了得到最高分,我们就必须在最后机器人蓄力的时候击杀它,否则杀不掉。
综上我们要记遍历录下C最后的位置同时统计C的数量,然后遍历到C最后的位置统计B的数目,如果能量为0,那么杀不掉。
同时特判如果没有C也是杀不掉。

代码

#include
#include
#include
using namespace std;
int main()
{
 int n;
    cin>>n;
    string a;
    cin>>a;
    int cnt=0;
    int ans=-1;
    int jj=0;
    for(int i=0;i<n;i++){if(a[i]=='C'){ans=i;cnt++;}}
    for(int i=0;i<ans;i++){if(a[i]=='B')jj++;}
    if(cnt+jj-1<=0||ans==-1)cout<<"draw";
       else cout<<cnt+jj-2;
}

⭐️C.Gold Rong 的数组

第五届太原理工大学新生赛(决赛)题解_第4张图片

题意

对一个长度为n的初始元素为0的数组进行修改,每次选择一个位置x,一个正整数y,将数组每个数加上max(y-abs(x-i),0),经过q此修改后数组是什么

解决思路

第五届太原理工大学新生赛(决赛)题解_第5张图片

通过观察我们可以发现,有些位置不会受到影响还是原来的值0,通过计算我们可以得到对于一次操作,

  • 最左端影响到L=max(x-y,1)
  • 最右端影响到R=min(x+y,n)
    最大长度为2y,然后进行修改即可

代码

#include 
using namespace std;
const int N = 1e5+10;
int a[N];
int main()
{
    int n,q;
    cin>>n>>q;
    while(q--){
        int x,y;
        cin>>x>>y;
        int l = max(x-y,1);
        int r = min(x+y,n);
        for(int i = l;i<=r;i++)
        {
            a[i] +=max(y-abs(x-i),0);
        }
    }
    for(int i = 1;i<=n;i++)
        cout<<a[i]<<" ";
    return 0;
}

⭐️D.勇敢鼠鼠

第五届太原理工大学新生赛(决赛)题解_第6张图片

题意

n个数中选择n-1个数进行|运算然后又n种选择,输出n个方案的最大值,注意数据范围

解决思路

构造前缀或,后缀或,算出n种答案,选最大值

代码

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
long long  a[210000],b[210000],c[210000];
int main()
{   
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) {
        cin>>a[i];
        b[i]=a[i];
        c[i]=a[i];
    }
    for(int i=2;i<=n;i++)
    {
        b[i]=b[i]|b[i-1];
    }
    for(int i=n-1;i>=2;i--){
        c[i]=c[i]|c[i+1];
    }
    long long ans=0;
    for(int i=2;i<n;i++){
        ans=max(ans,b[i-1]|c[i+1]);
    }
    ans=max(ans,c[2]);
    ans=max(ans,b[n-1]);
    cout<<ans;
    return 0;
}

⭐️E.syuggie的彩票

第五届太原理工大学新生赛(决赛)题解_第7张图片

题意

给定一个彩票刮开了一部分,只有仅有k个1连在一起才算中奖,输出可能个数,没有则输出delicious

解决思路

创建滑动窗口统计k区间内是否都是1,外面是否都是0,计数即可。

代码

#include
using namespace std;
#define fi first
#define se second
#define endl "\n"
#define ll long long
#define ull unsigned ll
#define pb push_back
#define all(v) v.begin(),v.end()
#define PII pair<int,int>
#define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i=(int)a,i##i=(int)b;i<=i##i;i++)
#define per(i,a,b) for(int i=(int)a,i##i=(int)b;i>=i##i;i--)
const int N=1e5+5;
int c0[N],c1[N];
void solve(){
	int n,k; cin>>n>>k;
	string s; cin>>s; s=" "+s; 
	rep(i,1,n){
		c0[i]=c0[i-1]+(s[i]=='0');
		c1[i]=c1[i-1]+(s[i]=='1');
	}
	int ans=0;
	rep(i,k,n){
		if(c0[i]-c0[i-k]==0&&!c1[i-k]&&!(c1[n]-c1[i])) ans++;
	}
	if(ans) cout<<ans<<endl;
	else cout<<"delicious"<<endl;
}
int main(){
	IOS; 
	int T=1; 
	while(T--) solve();
}

⭐️F.A hard problem


⭐️G.An easy string problem

第五届太原理工大学新生赛(决赛)题解_第8张图片

题意

给一个字符串修改一个字符成为字典序最小的回文串

解决思路

因为题目给了只需修改一个字符,则证明只有一个字符不同当字符串长度为偶数时,找到不同的位置看那个字典序小就换成那个。奇数时把中间位置字符换掉,如果为a则换成b否则都换成a。

代码

#include
using namespace std;
int main()
{
    int n;cin>>n;
    string a;cin>>a;
    vector<int>b(n);
    char c,d;
    int j=0;
    int cnt=0,ans;
    for(int i=0;i<n/2;i++)
    {
        if(a[i]!=a[n-1-i]){
            c=a[i],d=a[n-1-i];
            cnt=i,ans=n-1-i;
            j++;
        }
    }
    if(j>0){
    if(c>d){
    for(int i=0;i<n;i++)
    {
        if(i==cnt)cout<<d;
        else cout<<a[i];
    }}
    else
    {
        for(int i=0;i<n;i++)
        {
            if(i==ans)cout<<c;
            else cout<<a[i];
        }
    }}
    else{
        for(int i=0;i<n;i++)
        {if(i==n/2&&a[i]!='a')cout<<'a';
         else
         if(i==n/2&&a[i]=='a')cout<<'b';
         else cout<<a[i];
    }
    }}

⭐️H.An easy game

第五届太原理工大学新生赛(决赛)题解_第9张图片

题意

n个数字轮流选择一个数字和它的因子,谁不能拿了就赢了。

解决思路

,可以暴力搜索+特判。
但可以发现只有1时bob赢

代码

#include
using namespace std;
int main()
{
    int n;cin>>n;
    if(n>=2)cout<<"Alice";
    else cout<<"Bob";
}

⭐️I.饿饿饭饭是何意味

第五届太原理工大学新生赛(决赛)题解_第10张图片

题意

如果字符串有eat就输出eeffQAQ否则输出What does it mean?

解决思路

find 找一下位置,或者strstr

代码

#include
using namespace std;
int main()
{
    string a;
    cin>>a;
    if(a.find("eat")<=1000)cout<<"eeffQAQ";
    else cout<<"What does it mean?";
}

⭐️J.TYUT链


⭐️K.抢车位

第五届太原理工大学新生赛(决赛)题解_第11张图片

题意

有n个停车位,由于车主们害怕刮蹭,所以每次停车都停在离别的车最远的地方,特别的第一辆车停在最左边。问可以停多少车

解决思路

这个问题和广大男同胞上厕所有着大同小异的关系。
是一个坑位利用率的问题。怎么解决呢?
我们不难发现n=1时可以停1个即f(1)=1,f(2)=1,f(3)=2,f(4)=2;
打表可以发现规律a[i]=a[i/2]+a[i/2+1]-1;
a[i]=a[(i+1)/2]*2-1;
同时我们也可以想到当n大于2时每停一辆车都必须在两辆车之间停,所以就看看两辆车之间的距离能放多少车。

代码

#include
using namespace std;
int a[1000001];
int main()
{
    int n;
    cin>>n;
    a[1]=1;a[2]=1;a[3]=2;a[4]=2;
    if(n>4)
    {
        for(int i=5;i<=(n/2+1);i++)
        {
            if(i%2==0) a[i]=a[i/2]+a[i/2+1]-1;
            else a[i]=a[(i+1)/2]*2-1;
        }
        if(n%2==0) a[n]=a[n/2]+a[n/2+1]-1;
        else a[n]=a[(n+1)/2]*2-1;
    }
    cout<<a[n]<<endl;
}

⭐️L.Syuggie的减肥计划

第五届太原理工大学新生赛(决赛)题解_第12张图片

题意

每24小时必须吃一顿,给出一日三餐热量使得结束时热量最小

解决思路

可以动态规划,从第一天吃早午晚饭记录下每次选择的方案到最后比最小。
同时也可以进行贪心先选择第一天最小的,然后选择这一天后三顿最小的,继续选择,可以用queue实现。

代码

#include
using namespace std;
int d[100005][3];
int main()
{
	int n,i,j;
	cin>>n;
	for(i=1;i<=n;i++)
	cin>>d[i][0]>>d[i][1]>>d[i][2];
	for(i=n-1;i>=1;i--)
	{
	    d[i][2]+=min(d[i+1][0],min(d[i+1][1],d[i+1][2]));
		d[i][1]+=min(d[i+1][1],min(d[i][2],d[i+1][0]));
		d[i][0]+=min(d[i+1][0],min(d[i][1],d[i][2]));
	}
	cout<<min(d[1][0],min(d[1][1],d[1][2]));
	return 0;
}

⭐️M.公平分配


⭐️N.A+B problem

第五届太原理工大学新生赛(决赛)题解_第13张图片

题意

给两个数字竖式向左对齐相加

解决思路

少的位数补0相加即可

代码

#include
using namespace std;
#define int long long
int shu(int n)
{
    int cnt=0;
    while(n)
    {
        cnt++;
        n/=10;
    }
    return cnt;
}
int ss(int u)
{
    int sum=1;
    while(u--)sum*=10;
    return sum;
}
signed main()
{
    int a,b;
    cin>>a>>b;
    int c=shu(a);
    int d=shu(b);
    if(c>d){b=b*ss(c-d);cout<<a+b;}
    if(c==d)cout<<a+b;
    if(c<d){a=a*ss(d-c);cout<<a+b;}
}

你可能感兴趣的:(刷题,c++,算法)