河南萌新联赛2024第(六)场:郑州大学

装备二选一(一)

66E61d 沉迷 RPG 游戏,且喜欢与人比赛打木桩(双方分别对两个完全相同且无限血量的目标进行普通攻击,规定时间内输出高的一方获胜)。这天 66E61d 击败了一只 boss 后发现该 boss 掉落了一件武器,66E61d 想知道这件武器是否能替换掉他手中的武器,使他当天晚上可以在打木桩比赛中获得更高的输出能力。

已知 66E61d 的普通攻击有 0 % 0\% 0% 的概率产生暴击,我们称这个概率为暴击率,普通攻击伤害不为 0 0 0

* 手中的武器会为他增加 a % a\% a% 的暴击率,发生暴击时会使他本次普通攻击伤害变为原来的 b b b 倍。
* boss 掉落的武器会为他增加 c % c\% c% 的暴击率,发生暴击时会使他本次普通攻击伤害变为原来的 d d d 倍。
输入描述
输入一行四个整数 输入一行四个整数 a ,   b ,   c ,   d    ( 0 ≤ a ,   c ≤ 100 ,   1 ≤ b ,   d ≤ 10 ) a,\ b,\ c,\ d\ \ (0\leq a,\ c\leq 100,\ 1\leq b,\ d\leq10) a, b, c, d  (0a, c100, 1b, d10)
输出描述
若 boss 掉落的装备可以使 66E61d 获得更高的输出能力,输出 `YES` ,否则输出 `NO` 。

解题思路

比较攻击力的增量

AC代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
#define fi first
#define se second
#define PII pair<int,int>
#define ALL(x) x.begin(),x.end()
const int N=2e5+10;
void solve()
{
	int a,b,c,d;cin>>a>>b>>c>>d;
    if(c*(d-1)>a*(b-1))    cout<<"YES";
    else    cout<<"NO";
}

signed main()
{
    IOS
    int t;
    // cin>>t;
    t=1;
    while(t--)solve();
    return 0;
}

百变吗喽

”你说得对,但是《黑神话:悟空》为中国大陆游戏公司游戏科学开发的一款动作角色扮演游戏,采用虚幻5引擎制作,以小说《西游记》为背景设定,玩家将扮演一位“天命人”,为了探寻昔日传说的真相,踏上一条充满危险与惊奇的西游之路。游戏于2020年8月20日公布首段实机演示,在2023年12月8日官方发布的发售日短片中宣布游戏发售日期为2024年8月20日。”

你虽然不是大圣也不是天命人,去不了西天取不了经,但你作为百变吗喽能够帮助小豫同学完成暑假作业,你可以变成任意一个小写字母,然后插入到小豫同学所写的单词中,来使得小豫同学最终的单词和正确答案一模一样。

现在给你小豫同学所写的单词 s s s,和标准答案 t t t (均为只由小写字母组成的字符串,且一定有 l e n ( s ) = l e n ( t ) − 1 len(s) = len(t)-1 len(s)=len(t)1 ),你变为任意一个字母插入到任意位置(某个字母的后面或者整个单词的最前面)。 问有多少种插入的方案能够使得插入字母后 s s s t t t 相同,并给出每种方案的插入位置和变化的字母。
输入描述
第一行输入一个字符串 s s s
第二行输入一个字符串 t t t
保证 ( 1 ≤ l e n ( s ) < 1 0 6 ) ( 1\le len(s) < 10^6 ) (1len(s)<106)
输出描述
第一行输出方案数 n n n,
接下来的 n n n 行,每行一个数字 x x x 和一个小写字母 c h ch ch ,分别表示插入的位置(即插入在第 x x x 个字母的后面,若插入在整个单词的前面, x = 0 x = 0 x=0 ) ,以及你要变换的字母。
要求你输出的 n n n 个方案按照 x x x 从小到大排序,如果 x x x相同,那么按照 c h ch ch的ASCII码从小到大排序。

解题思路

正序找不同点,逆序找不同点,比较不同点位置

AC代码

#include<bits/stdc++.h>
using namespace std;
string s,t;
int main()
{
    cin>>s>>t;
    int l=s.size();
    int x=0,y=0;
    while(x<l&&y<=l&&s[x]==t[y])    x++,y++;
    int a=l-1,b=l;
    while(a>=0&&b>=0&&s[a]==t[b])    a--,b--;
    if(a<=x) // 倒序不同点位置小于或等于正序不同点位置
    {
        cout<<x-a<<'\n';
        for(int i=a+1;i<=x;i++)
        {
            cout<<i<<' '<<t[x]<<'\n';
        }
    }
    else    cout<<"0";
    return 0;
}

16进制世界

这是一个16进制的世界,比如522的16进制是20A。

在5月22日那天,有人送给Bob一些月饼,每个月饼有饱食度和幸福度两个属性。

现在Bob有 n n n个月饼,对于每个月饼 i i i,饱食度为 v i v_i vi,幸福度为 w i w_i wi

Bob现在有 m m m饱食度,意味着他吃的月饼的饱食度之和不大于 m m m

但是由于Bob身处16进制的世界,他吃的月饼的幸福度之和必须是16的倍数。

请帮Bob算一下他最多吃的月饼的数量。
输入描述
第一行输入两个整数 n ,   m n,\ m n, m

接下来 n n n行分别输入 v i ,   w i v_i, \ w_i vi, wi表示第 i i i个月饼的饱食度和幸福度。

输入数据保证 1 ≤ n ⋅ m ≤ 1 0 5 1 \leq n \cdot m \leq 10^5 1nm105, 1 ≤ v i ≤ 1 0 5 1 \leq v_i \leq 10^5 1vi105, 1 ≤ w i ≤ 1 0 9 1 \leq w_i \leq 10^9 1wi109
输出描述
一个整数,表示Bob最多能吃的月饼数量

解题思路

01背包,幸福度为16的倍数,利用16的余数,二维背包

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,m,inf=1e9;
int main()
{
	cin>>n>>m;
	vector<vector<int> >f(m+1,vector<int>(16,-inf));//初始化为极小值
	f[0][0]=0;
    // 01背包
	while(n--)
	{
		int v,w;cin>>v>>w;
		w%=16; // 利用 16 的余数
		for(int j=m;j>=v;j--)
		{
			for(int k=0;k<16;k++) // 遍历所有的余数
			{
				f[j][(k+w)%16]=max(f[j][(k+w)%16],f[j-v][k]+1);
			}
		}
	}
	int ans=0;
     // 寻找体积为 i 的最大值
    
	for(int i=0;i<=m;i++)	ans=max(ans,f[i][0]);
	cout<<ans;
	return 0;
}

四散而逃

有一个由n个格子排成一行的走廊,边缘的格子为走廊的尽头(即 1 1 1号格子和 n n n号格子), 起初第 i i i个格子上都有 a i a_i ai个人。每次**奔逃**操作会使得同一个格子的两个人,向两侧奔逃到某个格子停下。即每次操作会选择三个下标 i , j , k i,j,k i,j,k, 其中 1 ≤ i < j < k ≤ n 1 \le i<j<k \le n 1i<j<kn ,并且 a j ≥ 2 a_j \ge 2 aj2 , 从 j j j号格子中选择两个人分别逃到 i i i号格子和 k k k号格子。

问最少需要多少次 ** 奔逃 ** 才能够让所有人都到达 1 1 1号格子或者 n n n号格子。若无论多少次操作都做不到,就输出`-1`

*注:应该说是二散而逃才对(o´罒`o)*
输入描述
第一行输入一个整数 n , ( 3 ≤ n ≤ 2 ∗ 1 0 5 ) n,(3 \le n \le 2 *10^5) n,(3n2105)
第二行输入n个整数 a 1 , a 2 , . . . , a n , ( 1 ≤ a i ≤ 1 0 9 ) a_1,a_2,...,a_n ,(1\le a_i \le 10^9) a1,a2,...,an,(1ai109)
输出描述
输出一个整数,表示需要最少的次数,或者-1

解题思路

分析得只要存在一个偶数(该偶数大于0),即可完成奔逃

AC代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
    int n,flag=0,ans=0,a;cin>>n;
    for(int i=1;i<=n;i++)
    {	
    	cin>>a;
    	if(i==1||i==n)	continue;
        if(a%2==0)	flag=1;
        ans=ans+(int)((a+1)/2);
    }
    if(flag==1)    cout<<ans;
    else    cout<<"-1";
    return 0;
}

追寻光的方向

“追寻光的方向,把你遗忘…”,听着歌,小G绕着校园在跑步。
为了简便起见,我们可以简单的认为小G在一条直线上跑步。夜晚降临,路灯在道路两旁笔直的挺立着,用自己的光驱散着黑暗。而小G要做的,就是一直追寻着最亮的那个路灯,用力向前跑去…
现已知小G所在的道路上排列着 n n n个路灯,由于学校电力系统的问题,每个路灯发出的光亮为 l i l_i li。而小G的跑步,由于视野问题,每次只能看到前方最亮的那盏灯的位置,(若前方有多个亮度值最大,则只会跑到第一个亮度值最大的位置)所以小G每次都会全力以赴的冲到最亮的那盏灯下,然后进行一次休息。现如今小G正在第一个路灯下,请问小G如果想到达第 n n n个路灯下,需要休息几次?
例:如果当前路灯的亮度值分别是 4 , 3 , 5 , 7 , 1 4,3,5,7,1 4,3,5,7,1,则小G最初在亮度值为 4 4 4的路灯下,视野前方路灯值为 3 , 5 , 7 , 1 3,5,7,1 3,5,7,1其中最亮的是 7 7 7,所以小G就会跑到亮度值为 7 7 7的路灯下,然后进行休息,之后视野前方路灯值为 1 1 1,则小G跑到亮度值为 1 1 1的路灯下,也就是最后一个路灯下,完成目标,总共需要休息一次。
输入描述
第一行一个正整数,表示 n n n.
第二行 n n n个正整数,表示 n n n个路灯的亮度值 l i l_i li
对于100%的数据, 1 ≤ n ≤ 1 0 5 , 1 ≤ l i ≤ 1 0 9 1 \leq n \leq 10^5, 1\leq l_i\leq 10^9 1n105,1li109
输出描述
一行一个整数表示需要休息的次数。

解题思路

倒序比较较大值,每次更新,即为休息的次数

AC代码

#include<bits/stdc++.h>
using namespace std;
int a[100010];
int main()
{
    int n;cin>>n;
    for(int i=1;i<=n;i++)    cin>>a[i];
    int ma=a[n],ans=0;
    for(int i=n-1;i>1;i--)
        if(a[i]>=ma)
        {
            ans++;
            ma=a[i];
        }
    cout<<ans;
    return 0;
}

等公交车

小G和朋友约好了时间出去玩,他选择坐公交车去找对方。

早早的便来到了公交站牌处开始了等公交车,但公交车却迟迟不来,终于在他濒临爆发的时候,公交车终于缓缓开来。开心的和朋友会合后,他们便开始了一天的玩乐。回到家后,小G还是对于等公交车耿耿于怀,现已知每天都会发出 m m m辆公交车,在手机上它可以查出这 m m m辆公交车的发车时刻第 t i t_i ti分钟,并且他还知道所有的站点信息,总共有 n n n个公交车站点,第 i i i 个站点距离发车点的距离为 d i d_i di米。已知公交车的速度为 1 1 1米/分钟,发车点和所有的站点都在一条直线上, 每次公交车从发车点出发后,依次经过每个站点。他想知道能否设计一个程序,当每次一个乘客在某个时刻时到达某个站点时,可以直接告诉他需要等待的时间?
输入描述
第一行两个个正整数,表示 n , m n,m nm.
第二行 n n n个正整数,表示 n n n个站点距离发车点的距离 d i d_i di.(数据保证 d i d_i di递增)
第三行 m m m个正整数,表示 m m m辆公交车的发车时刻 t i t_i ti.(数据保证 t i t_i ti递增)
第四行一个正整数 Q Q Q,表示接下来的询问个数。

接下来 Q Q Q行,每行两个正整数 t , x t,x t,x,表示该乘客在时刻 t t t时来到了 x x x号站点。

对于100%的数据, 1 ≤ n , m , q ≤ 1 0 5 , 1 ≤ l i , t i ≤ 2 × 1 0 9 1 \leq n,m, q \leq 10^5, 1\leq l_i,t_i\leq 2\times 10^9 1n,m,q105,1liti2×109
输出描述
Q行,每行一个整数表示需要等待的时间,若该乘客任何公交车都无法乘上,请输出`TNT`

解题思路

每次比较 每个公交车 到该站点的时间

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int d[N],t[N];
int main()
{
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++)    cin>>d[i];
    for(int i=1;i<=m;i++)    cin>>t[i];
    int q;cin>>q;
    while(q--)
    {
        int tt,x;cin>>tt>>x;
        if(tt>d[x]+t[m])    cout<<"TNT\n";
        else
            for(int i=1;i<=m;i++)
                if(d[x]+t[i]>=tt)
                {
                    cout<<d[x]+t[i]-tt<<'\n';
                    break;
                }
    }
    return 0;
}

24点

在扑克牌中有种玩法叫做24点,目标是用给定的四张牌通过基本的数学运算(加、减、乘、除)得到24。24点的玩法规则如下:

1. 准备一副扑克牌,去掉大小王,使用 `A,2,3,4,5,6,7,8,9,10,J,Q,K` 分别表示 `1,2,3,4,5,6,7,8,9,10,11,12,13`。每种各四张,共52张牌。
2. 每次从这些牌中任意取出四张牌。
3. 使用这四张牌的数字,通过加法、减法、乘法和除法运算,最终得到24。(除法是正常的数学除法,即有可能出现除不尽的情况,比如 1 ÷ 3 = 1 3 1\div 3=\dfrac13 1÷3=31
4. 每张牌只能使用一次,可以任意调换数字的顺序,可以使用任意的括号来改变运算顺序。
5. 玩家需要找到至少一种解决方案。如果无法用四张牌得到24点,则说明没有解。

现在需要你判断某种情况下是否有解。
输出描述
第一行一个正整数 T T T ( 1 ≤ T ≤ 1000 ) (1\le T\le 1000) (1T1000),表示数据的组数。

接下来 T T T 行,每行四个字符串,表示取出的四张牌的点数,输入的扑克牌点数只会出现 `A,2,3,4,5,6,7,8,9,10,J,Q,K`。
输入描述
输出一行一个字符串,如果有解输出 `YES`,无解输出 `NO`

解题思路

深搜,每次选择两个数进行数学运算(加、减、乘、除),最后剩余一个数时与24点比较

AC代码

#include<bits/stdc++.h>
using namespace std;  
unordered_map<string, int>m = {  
    {"A", 1}, {"2", 2}, {"3", 3}, {"4", 4}, {"5", 5},  
    {"6", 6}, {"7", 7}, {"8", 8}, {"9", 9}, {"10", 10},  
    {"J", 11}, {"Q", 12}, {"K", 13}  
};  
bool c(vector<double> n) {  
    if (n.size() == 1) return abs(n[0] - 24) <1e-12;  
    for (int i = 0; i < n.size(); ++i)
    {
        for (int j = 0; j < n.size(); ++j)
        {
            if (i != j)
            {  
                vector<double> r;  
                for (int k = 0; k < n.size(); ++k)
                {
                    if (k != i && k != j)
                    {
                        r.push_back(n[k]);
                    }
                }
                for (int op = 0; op < 4; ++op)
                {  
                    if (op < 2 && i > j) continue;  
                    switch (op)
                    {  
                        case 0: r.push_back(n[i] + n[j]); break;  
                        case 1: r.push_back(n[i] * n[j]); break;  
                        case 2: r.push_back(n[i] - n[j]); break;  
                        case 3: if (n[j] != 0) r.push_back(n[i] / n[j]); break;  
                    }  
                    if (c(r)) return true;  
                    r.pop_back();  
                }
            }  
        }
    }
    return false;  
}  
int main() {  
    int t;  
    cin >> t;  
    while (t--) {  
        vector<double> v(4);  
        for (int i = 0; i < 4; ++i)
        {  
            string s;  
            cin >> s;  
            v[i] = m[s];  
        }  
        sort(v.begin(), v.end());  
        do
        {  
            if (c(v)) {  
                cout << "YES" << endl;  
                break;  
            }  
        } while (next_permutation(v.begin(), v.end()));  
        if (!c(v)) cout << "NO" << endl;  
    }  
    return 0;  
}

正义从不打背身

*“正义之枪从不打背身”*。小x最近迷上了无畏契约,钟爱"正义"这把武器。可他使用该武器有一条原则:不击杀(打不中)背对自己的敌人。小x实力强大,对于所有直面自己的敌人都能一击毙命。

在一次游戏中。小x面前有 n n n个点位,从左往右序依次为 1 , 2 , 3 , … … , n 1,2,3,……,n 1,2,3,……n。每个点位上都有一个敌人。

每个敌人 要么正面朝向小x,要么背面朝向小x。

小x实力强大,打算强迫这n个敌人玩 m m m轮小游戏之后再对每个人开枪。

游戏规则如下:

在第 i i i轮小游戏中,依次执行以下所有操作:

* 序号为 [ 1 , i ] [1,i] [1,i]的点位上的敌人位置改变。改变规则为: 从 1 , 2 , 3 , … … , i 1,2,3,……,i 1,2,3,……i 变为 i , i − 1 , … … , 3 , 2 , 1 i,i-1,……,3,2,1 ii1,……,3,2,1(原来位于i号位置的敌人更换到1号位置,位于i-1号位置的敌人更换到2号位置……)

* 序号为 [ 1 , i ] [1,i] [1,i]的点位上的敌人原地旋转180°。

所有小游戏过后,小x想知道。目前在每个点位的敌人是否被击败。
输入描述
第一行输入两个整数 n , m n,m n,m

接下来一行输入一个仅由’P’和‘B’组成的字符串s。 s i = ′ P ′ s_i='P' si=P 表示第i个点位的敌人当前正面对小x。 s i = ′ B ′ s_i='B' si=B表示第i个点位的敌人当前正背对小x。

对于所有数据保证: 1 ≤ m ≤ n ≤ 2 × 1 0 6 1\le m \le n\le 2\times 10^6 1mn2×106 ∣ s ∣ = n |s|=n s=n
输出描述
输出一行n个整数。对于第i个数,如果目前位于第i个点位的敌人被击败则输出1,否则输出0。

AC代码

#include<bits/stdc++.h>
using namespace std;
string s,s1;
int main()
{
    int n,m;cin>>n>>m;
    cin>>s;
    s1=s;
    int j=0,k=m-1;
    for(int i=m-1;i>=0;i--)
    {
    	if((m-i)%2==1)
    	{
    		if(s[i]=='P')	s1[j++]='B';
    		else	s1[j++]='P';
    	}
    	else
    	{
    		if(s[i]=='P')	s1[k--]='P';
    		else	s1[k--]='B';
    	}
    }
    for(int i=0;i<n;i++)	cout<< (string)(s1[i]=='B' ? "0 " : "1 ");
    return 0;
}

koala的程序

koala设计了一个程序,首先他写了一个暴力算法,但是在他写完之后受到电脑病毒的影响而失忆。好在他的源代码和题面数据范围保留了下来(数据范围在输入描述中已经给出),但是现在仍然无法通过这个题目。由于电脑病毒的影响,题面已经消失,现在他希望你基于源代码做出优化来解决这道题。

C++代码:

#include <bits/stdc++.h>
using namespace std;

// 链表结构体定义
typedef struct node {
    int id;
    struct node \*next;
} \*pNode, Node;

// 循环链表头节点
pNode head;

// 按顺序删除的前n-1个节点的id构成的列表
vector<int> ans;

int main() {
    // n个节点,判断值k
    int n, k;
    cin >> n >> k;

    // 构造包含n个节点的循环链表
    head = (pNode)malloc(sizeof(Node));
    pNode now = head;
    for (int i = 1; i <= n; ++i) {
        pNode a = (pNode)malloc(sizeof(Node));
        a->id = i;
        now->next = a;
        now = now->next;
    }
    now->next = head->next;

    // pc为计数器
    int pc = 0;
    now = head;

    // 当前节点的上一个节点
    pNode last = nullptr;

    // 程序执行到链表只剩下最后一个节点为止
    while (n > 1) {
        pc++;
        last = now;
        now = now->next;
        // 当计数器pc = k时从循环链表中删除当前节点,并把被删除的节点的id添加到答案列表ans中
        if (pc == k) {
            last->next = now->next;
            n--;
            pc = 0;
            ans.push\_back(now->id);
        }
    }

    // 输出最终答案
    for (auto id : ans) {
        cout << id << ' ';
    }

    return 0;
}

输入描述
一行包合两个整数 n , k ( 2 ≤ n ≤ 3 ∗ 1 0 5 , 1 ≤ k ≤ 3 ∗ 1 0 5 ) n, k (2 \le n \le 3 * 10^5 , 1 \le k \le 3 * 10^5) n,k(2n3105,1k3105)
输出描述
根据题意输出答案

输入
 10 3
 
输出
 3 6 9 2 7 1 8 5 10

解题思路

由代码和样例得,为约瑟夫环问题

AC 代码

#include<bits/stdc++.h>
using namespace std;
int main() {
    int n, k;
    cin >> n >> k;
    deque<int> c;
    for (int i = 1; i <= n; ++i) {
        c.push_back(i);
    }
    int cur = 0;
    int cnt=0;
    while (!c.empty()) {
        cnt++;
        if(cnt==n)break;
        cur = (cur + k - 1) % c.size();
        cout << c[cur] << " ";
        c.erase(c.begin() + cur);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值