第九届“图灵杯”NEUQ-ACM程序设计竞赛个人赛前十题(能力有限)

A - 大学期末现状

题目描述

作为一名大学生的你,现在又到了期末查成绩的时候,当你的成绩大于等于60时请输出“jige,haoye!”,否则输出"laoshi,caicai,laolao"。

输入描述:

一行,一个整数x代表你的成绩(0<=x<=100)

输出描述:

一行字符串

示例1

输入

60

输出

jige,haoye!

这道题没什么说的,直接暴力。 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
	int x;
	cin >> x;
	if (x >= 60)cout << "jige,haoye!" << endl;
	else cout << "laoshi,caicai,laolao" << endl;
}

B - G1024
 

题目描述

期末考试结束后,图灵杯出题组的几位同学卑微地留在校出题,但是由于疫情影响,他们不得不尽快乘坐G1024号火车离开学校 ,现在假设图灵杯出题组共n人,并且通过APP可以知道G1024在接下来k天的已购票数x,总票数m,现在Phenix想知道在所有人都一起上火车的前提下最早在第几天可以离开学校,如果无论怎样都无法离开请输出“G!”

输入描述:

 
 

第一行两个整数n,k,表示出题组人数和天数(n,k<1000)

接下来k行,第i行两个整数x,m表示接下来第i天G1024的已购票数和总票数(0<=x<=m<1000)

输出描述:

一行,在所有人都一起上火车的前提下最早在第几天可以离开学校,如果不能离开请输出“G!”

 示例1

输入

7 5
100 100
99 100
95 100
900 1000
0 1000

输出

4

 仍然暴力。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
	int n, k;
	cin >> n >> k;
	int x, m;
	int flag = 0;
	for (int i = 1; i <= k;i++)
	{
		cin >> x >> m;
		if (m - x >= n)
		{
			cout << i << endl;
			flag = 1;
			break;
		}
	}
	if (!flag)cout << "G!" << endl;
	return 0;
}

C - NEUQ
 

题目描述

一天Phenix得到了一个长度为n的字符串,字符串仅由大写字母A~Z组成,现在Phenix想知道最少需要删除多少个字符使字符串变成NEUQNEUQ……这种由若干个"NEUQ"组成的形式。

输入描述:

第一行一个整数n,表示字符串长度(n<=10^6)
第二行一个字符串

输出描述:

一个整数,表示最少需要删除的字符数量

示例1

输入

10
NEUUQNEUQQ

输出

2

示例2

输入

9
ILOVENEUQ

输出

5

这道题方法很多,我用的是队列。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 1e6 + 5;
char s[N];
struct yyx
{
	char c;
};
queue<yyx>q;
int main()
{
	ll n;
	cin >> n;
	ll ans = 0;
	for (ll i = 1; i <= n; i++)
	{
		cin >> s[i];
		if (q.size()%4 == 0 && s[i] == 'N')
		{
			q.push({ 'N' });
		}
		else if (q.size()%4 == 1 && s[i] == 'E')
		{
			q.push({ 'E' });
		}
		else if (q.size()%4 == 2 && s[i] == 'U')
		{
			q.push({ 'U' });
		}
		else if (q.size()%4 == 3 && s[i] == 'Q')
		{
			q.push({ 'Q' });
		}
		else ans++;
	}
	if (q.size()%4 != 0)ans += q.size()%4;
	cout << ans << endl;
	return 0;
}

 D - 小G的任务
 

题目描述

Phenix在验完题目之后,觉得图灵杯里面的简单题太多了,不符合图灵杯考验算法编程能力的初衷,决定增加一道难度更大的题目,将出题的任务交给了小G 。

众所周知,小G的水平十分有限,目前无法原创难度大的题目,于是他打算去各大oj里面白嫖题目 。

目前小G能查询到的oj一共有n 个 , 对于第i 个oj, 可以白嫖的难度合适题目数量我们定义为ai,ai​ 的大小定义为 数字i 的各数位之和 。

例如  ,i=233,ai=2+3+3=8。

 i=2048,ai=2+0+4+8=14。

现在给定 有n 个oj可以白嫖 , 小G想知道,最后他有多少个题目可以白嫖 。
即求

n

∑   ​ai​。

i=1

输入描述:

一个正整数n<=1000000

输出描述:

一个正整数表示有多少个题目可以白嫖

示例1

输入

9

输出

45

示例2

输入

99

输出

900

这道题我的思路是先把每个数的ai求出来然后存在数组里

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 1e6 + 5;
int a[N];
void shai()
{
	for (ll i = 1; i < N; i++)
	{
		ll ii = i;
		int ans = 0;
		while (ii)
		{
			ans += ii % 10;
			ii /= 10;
		}
		a[i] = ans;
	}
}
int main()
{
	ll n;
	cin >> n;
	shai();
	ll ans = 0;
	for (ll i = 1; i <= n; i++)
	{
		ans += a[i];
	}
	cout << ans << endl;
	return 0;
}

E - nn与游戏
 

nn最近突然对做游戏非常感兴趣,于是他去找做游戏的xf询问相关话题,而xf此时正好在做一个游戏demo。
目前游戏中有一个n×n大小的地图,里面有若干个可控制的己方单位、与己方单位同数量的敌对单位和一些障碍物。为了充分达成对各个单位的克制,玩家需要手动控制各个不同单位移动到自己所克制的敌对单位附近攻击。
现在xf将这样一个功能的实现强行塞给了nn:需要让玩家立刻了解到自己可控制的所有单位是否能绕过各个障碍移动到各自所克制的地方单位附近。
你能帮nn解决这个问题吗?
 

输入描述:

第1行输入n,m,代表该地图大小为n×n,存在m个障碍。
第2∼m+1行每行依次输入行x,y代表每个障碍的坐标位置。
第m+2行输入t,代表总共有t个可控制单位和t个敌对单位。
第m+3行往后每行依次输入x1,y1,x2,y2​,(x1,y1)代表一个己方可控制单位的位置,(x2,y2)代表被其克制的敌对单位的位置(即该可控制己方单位的目标点)。
数据保证任何单位与障碍都不会出现重叠,地图的x,y坐标都位于[0,n)范围内。
1≤n≤103,0≤m<10^6
1≤t≤10,0≤x,y,x1,y1,x2,y2<n

输出描述:

按可控制单位坐标的输入顺序输出各个可控制单位是否能抵达对应敌对单位所在位置,若能抵达,输出抵达对应位置所需的最短步数,否则输出-1。
注:寻路过程中需要考虑单位间的阻挡(即一个单位不管是可控制单位还是敌对单位,都会成为其他单位的障碍物),但因为只是计算一个时间点的事情,所以在计算时默认其他单位都在原来位置静止不动就行。

示例1

输入

3 1
1 0
2
0 0 1 1
0 1 2 2

输出

-1

3

说明

地图如下(a,b为可控制单位,对应克制的敌对单位为c,d,障碍物为1,空位置为0)

00d 
bc0 
a10

如图可见,a去c的路程被b和1挡住了,故输出-1;b可以通过向上,向右,向右,三步到达d,此路径为b到达d的最短路径,故输出3

稍微加了点料的dfs,一开始我一直内存超限,后面反应过来是写的稍微有点瑕疵,把一个判定条件写在外面了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
ll m;
int t;
int zhangaix, zhangaiy;
int xx1, yy1, xx2, yy2;
int map1[1002][1002];
int panduan[1002][1002];
int sum[1002][1002];
int cun[1002][4];
struct yyx
{
	int x, y;
};
int dx[4] = { 1, 0, -1, 0 }, dy[4] = { 0, -1, 0, 1 };
void bfs(int a,int b,int c,int d)
{
    queue<yyx>q;
	memset(sum, -1, sizeof sum);
	memset(panduan, 0, sizeof panduan);
	q.push({a,b});
    panduan[a][b]=1;
	map1[c][d] = 0;
	sum[a][b] = 0;
	while (q.size())
	{
		auto t = q.front();
		q.pop();
		for (int i = 0; i < 4; i++)
		{
			int xx = dx[i] + t.x;
			int yy = dy[i] + t.y;
			if (xx >= 0 && xx < n&&yy >= 0 && yy < n&&panduan[xx][yy] == 0 && map1[xx][yy] == 0)
			{
				sum[xx][yy] = sum[t.x][t.y] + 1;
				q.push({ xx, yy });
                panduan[xx][yy]=1;
			}
		}
	}
	map1[c][d] = 1;
	cout << sum[c][d] << endl;
}
int main()
{
	cin >> n >> m;
	while (m--)
	{
		cin >> zhangaix >> zhangaiy;
		map1[zhangaix][zhangaiy] = 1;
	}
	cin >> t;
	for (int i = 1; i <= t; i++)
	{
		cin >> cun[i][0] >> cun[i][1] >> cun[i][2] >> cun[i][3];
		map1[cun[i][0]][cun[i][1]] = 1;
		map1[cun[i][2]][cun[i][3]] = 1;
	}
	for (int i = 1; i <= t; i++)
	{
		bfs(cun[i][0], cun[i][1], cun[i][2], cun[i][3]);
	}
	return 0;
}

 F - 第二大数
牛神对于第一的宝座感到厌倦,他开始研究第二大的贡献。
现在给你一个N个数的排列P,包含(1,2,...,N),其中对于任给的一组(L,R)(1≤L<R≤N) ,定义XL,R​为序列元素从下标L到R中第二大的数。
现在请聪明的你算出 

N−1   N

∑       ∑         XL,R的结果,AC者可凭运气获得牛神签名照一张。

L=1   R=L+1
 

输入描述:

 
 

第一行为牛神想要研究的数字N,其中2≤N≤10^4 。
第二行为N的一个排列。

输出描述:

输出包括一个整数,表示所求结果。

示例1

输入

3
2 3 1

输出

5

判断每一次的条件,然后暴力解决

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[10005];
int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	ll ans = 0;
	for (int i = 1; i <= n - 1; i++)
	{
		int zuida = max(a[i], a[i + 1]);
		int erda = min(a[i], a[i + 1]);
			for (int j = i + 1; j <= n; j++)
			{
				if (a[j] <= erda)ans += erda;
				else if (a[j] > erda&&a[j] < zuida)
				{
					erda = a[j];
					ans += erda;
				}
				else if ((a[j] > zuida))
				{
					erda = zuida;
					zuida = a[j];
					ans += erda;
				}
				else if (a[j] == zuida)
				{
					if (j != i + 1)
					{
						erda = zuida;
						zuida = a[j];
						ans += erda;
					}
					else ans += erda;
				}
			}
	}
	cout << ans << endl;
	return 0;
}

 G - Num

题目描述

Phenix有一个正整数N,他想知道正整数N是否可以写成a∗b+a+b的形式(其中a>0,b>0)
例如3=1∗1+1+1,如果可以请输出"Yes",否则输出"No"

输入描述:

一个正整数N(0<N<2×10^9)

输出描述:

“Yes”或者“No“

示例1

输入

2

输出

No

示例2

输入

8

输出

Yes

这道题一开始写的时候浪费了很长时间,首先我找了一下规律,发现只要是奇数,除了1都符合条件,用1和任意数组合得出的结论,然后判断偶数的时候怎么都没办法过,后来发现

n=a*b+a+b可以转换成n+1=(a+1)(b+1),所以只要n+1不是素数就可以实现

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
	ll n;
	cin >> n;
	ll nn = n + 1;
	int flag = 0;
	for (ll i = 2; i <= sqrt(nn); i++)
	{
		if (nn%i == 0)
		{
			flag = 1;
			break;
		}
	}
	if (flag)cout << "Yes" << endl;
	else cout << "No" << endl;
	return 0;
}

 H - 特征值
 

题目描述

最近捷宝学习了线性代数的知识,并成功在期末考试中获得了100分的好成绩。

其中计算矩阵的特征值这一题型给他留下深刻印象。

出于好奇心,他决定利用假期时间仔细钻研特征值这一概念。经过长达好多好多好多好多天的闭关研究,捷宝提出了整数的特征值这一概念。

可爱的捷宝定义,对于任意的正整数X,它的特征值的计算方式为:

             10100

特征值=∑         ⌊ x/(10^k)⌋

            k=0

注:⌊ ⌋为向下取整,即不超过当前数字的最大整数(⌊3.2⌋=3,⌊2.9⌋=2,⌊7⌋=7)

现在捷宝想要把概念进行推广,他需要你帮忙设计一个程序,能够对于任意读入的一个正整数,快速计算它的特征值.

输入描述:

输入共包括1行,输入捷宝想要研究的数字X

其中1≤X<10^500000

输出描述:

输出共包括一行,输出所研究数字的特征值

示例1

输入

1225

输出

1360

说明

1225+122+12+1=1360

示例2

输入

99999

输出

111105

说明

99999+9999+999+99+9=111105

示例3

输入

314159265358979323846264338327950288419716939937510

输出

349065850398865915384738153697722542688574377708317

备注:

提示:由于本题中读入数据的数据范围较大,所以可以考虑使用int类型的数组来存储X的每一位,以便于后续操作。
计算答案和输出答案也同理,可以使用数组来存储数字的每一位。

 由于数据太大,用数组存数。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 5e5 + 10;
char a[N];
int b[N];
int main()
{
	scanf("%s", a);
	ll len = strlen(a);
	ll shengyu = 0;
	ll len1 = 0;
	ll ans = 0;
	for (ll i = 0; i < len; i++)
		ans += a[i] - '0';
	while (len)
	{
		ll answer = ans;
		answer += shengyu;
		b[len1++] = answer % 10;
		shengyu = answer / 10;
		ans -= a[len - 1] - '0';
		len--;
	}
	if (shengyu)cout << shengyu;
	for (ll i = len1 - 1; i >= 0; i--)
		cout << b[i];
	cout << endl;
	return 0;
}

I - 最大公约数

题目描述

雯雯沉迷学习数学无法自拔,他在闭关修炼中遇到了难题,聪明的你能帮他解答吗?
现在给你一个N个数的序列P,定义X为这N个数的最大公因数,你可以进行无限次操作,每次操作选择一组(L,R)((1≤L≠R≤N,PL≥1),使得PL−1且PR+1,每次操作产生新的序列P。请问所有可能产生的P对应的X最多有多少个。AC者可凭RP获得雯雯签名照一张。
定义:A是序列P的一个公因数当且仅当序列P的每一个元素都能被A整除,且A≥1。
注意:本题规定任何正整数都是0的公因数。

输入描述:

 
 

第一行包含一个数N,其中2≤N≤500。

第二行为长度为N的一个序列,其中序列元素PPP满足
1≤P≤10^6。

输出描述:

输出包括一个整数,表示所有序列产生的最大公因数的个数。

示例1

输入

3
1 1 2

输出

3

说明

第一次操作,L=1,R=2,操作后P=0,2,2,此时P的最大公因数为2。

第二次操作,L=2,R=3,操作后P=0,1,3,此时P的最大公因数为1。

第三次操作,L=2,R=3,操作后P=0,0,4,此时P的最大公因数为4。

经过若干次操作后,序列P产生的最大公因数为1,2,4,共3个。

其实仔细思考一下就能发现这道题其实是求的n个数之和,我们称为sum,求的是sum的因子数。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
	ll sum = 0;
	ll n,x;
	cin >> n;
	while (n--)
	{
		cin >> x;
		sum += x;
	}
	ll ans = 0;
	for (int i = 1; i < sqrt(sum); i++)
	{
		if (sum%i == 0)ans += 2;
	}
	int s = sqrt(sum);
	if (sum%s == 0)ans++;
	cout << ans << endl;
	return 0;
}

J - 玄神的字符串

题目描述

玄神有一条珍藏多年的神奇字符串。因为某种原因,该字符串只由数字0和数字1组成。但是最近,他开始对字符串感到厌烦,所以他想将这个字符串删除。他可以任意进行以下三种操作,每种操作的次数不限:
1)选择字符串中的一个0和一个1,将他们删除,代价为a;
2)选择字符串中两个位置不同的0或者两个位置不同的1,将他们删除,代价为b;
3)将字符串中的一个0变成1或将字符串中的一个1变成0,代价为c。
聪明的你能不能帮帮玄神,求出将这条神奇字符串删除成空字符串(不含任何字符的字符串)的最小代价为多少?

输入描述:

 
 

第一行包括一个仅由数字0和数字1构成的字符串s,s的长度不超过50000,保证s的长度为偶数
第二行包括三个整数a、b、c,分别代表上述三种操作的代价。保证1≤a,b,c≤10000。

输出描述:

输出包括一个整数,表示删除该字符串的最小代价

示例1

输入

0110011001
3 4 5

输出

15

示例2

输入

0110011001
10 2 3

输出

13

其实不是很难的一道题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char s[50005];
int main()
{
    ll a, b, c;
    scanf("%s", s);
    cin >> a >> b >> c;
    ll ans = 0;
    ll ling = 0, yi = 0;
    for (ll i = 0; i < strlen(s); i++)
    {
        if (s[i] == '0')ling++;
        else yi++;
    }
    if (a <= b)
    {
        ll m = min(ling, yi);
        ans += m*a;
        ling -= m;
        yi -= m;
        if (a + c < b)
        {
            ans += (ling / 2 + yi / 2)*(a + c);
        }
        else ans += (ling / 2 + yi / 2)*b;
    }
    else
    {
        ans += (ling / 2)*b + (yi / 2)*b;
        ling %= 2;
        yi %= 2;
        if (ling&&yi)
        {
            if (b + c < a)ans += b + c;
            else ans += a;
        }
    }
    cout << ans << endl;
    return 0;
}

 完毕,欧威尔欧威尔!!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值