SDUT 2021 Spring Individual Contest(for 20) - 2

Taymyr is calling you

地址

近期WYL学长捐钱驰援武汉,已经捐完钱的他发现自己没有钱谈恋爱了,考虑到集训队的群里老会有红包,机智的他稍加思考写了一个程序,程序会在(m, 2m, 3m…)秒的时候自动抢红包。
群里 在1~z秒钟里平均n秒发一个红包( n, 2n, 3n… )。每个红包里都能抢到一块钱,最后需要计算WYL学长到底抢了多少钱?(这个是学长自己翻译的,翻译可能有误但是题意不会错)

input

输入只有一行三个整数 n,m,z 如题目描述 (1 ≤ n, m, z ≤ 1e4).

output

输出抢的红包总金额

example:

Input
1 1 10
Output
10
Input
1 2 5
Output
2
Input
2 3 9
Output
1

Time limit —— 1000 ms
Memory limit —— 262144 kB

代码:

#include<iostream>
using namespace std;
const int N=1e4+10;
int main()
{
	int n,m,z;
	cin>>n>>m>>z;
	int res=0;
	for(int i=n;i<=z;i+=n)
	{
		if(i%m==0) res++;
	}
	cout<<res<<endl;
}

City

地址

为了抗击病毒的袭击,WJS开始他的埋消毒水活动。
他将城市画图为一个n×m的地图,由n+1垂直线段和m+1水平线段,那么有(n+1)×(m+1)个 点。
他准备在符合的线段上消毒水让它挥发消毒(可重叠)。
线段要满足下列条件:
1.长度不是零。
2.线段的两个端点是网格点。
3.线段的中点是网格点。
他现在想找出有多少条这样的线段。

input

输入的一行包含两个整数。n,m(1≤n,m≤1000)。

output

输出满足条件线段的数量即可。

example:

Input
1 1
Output
0
Input
2 3
Output
14

Time limit —— 1000 ms
Memory limit —— 262144 kB

分析:
符合题目要求的线段可以分为三类:
① 横向且长度为偶数的线段
② 纵向且长度为偶数的线段
③ 边长为偶数的正方形的对角线
注意:n为列,m为行
下图为n=2,m=3的样例图
红色:横向=1x4
蓝色:纵向=2x3
黄色:对角线=2x2
总=4+6+4=14
样例分析
代码:

#include<iostream>
using namespace std;
int main()
{
	int n,m;
	long long res1=0,res2=0,res3=0;
	cin>>n>>m;
	for(int i=2;i<=n;i+=2)
	{
		res1+=n-i+1;
	}
	res1*=(m+1);//横向 
	for(int i=2;i<=m;i+=2)
	{
		res2+=m-i+1; 
	}
	res2*=(n+1);//纵向 
	for(int i=2;i<=n;i+=2)
	{
		for(int j=2;j<=m;j+=2)
		{
			res3+=(n-i+1)*(m-j+1)*2;//对角线 
		}
	}
	cout<<res1+res2+res3<<endl;
}

WERTYU

地址

gdl每天沉迷写程序,他的键盘键位布局如图。然而他认为他的键盘键位布局不合理,严重影响他撸代码的速度,因此gdl对键盘键位进行了调整。经过研究,他认为将键盘所有的键位向右移一格可以显著提高他的输入效率。比如当gdl按下键盘上的E键时,屏幕上会显示W。现在你知道了gdl在键盘上输入的一系列字符,请解出屏幕上显示的内容。

input

输入包含多行内容,每行可能包括数字,空格,大写字母(不包含Q A Z 因为gdl认为代码中出现这三个字母是不优雅的)以及上图键盘中出现的字符(不包含`,Tab键,Backspace键,control键,alt键,enter键等符号)

output

你需要给出gdl屏幕上显示的字符串。注意:空格 回车 不可以被忽略

example:

ER;VP,R YP CI[Y SV,/

WELCOME TO XUPT ACM.

Time limit —— 1000 ms
Memory limit —— 262144 kB

模拟题,折磨人用的
代码:

#include<iostream>
#include<string.h>
using namespace std;
const int N=1e6+10;	char a[N];
int main()
{
	while(gets(a))
	{
		for(int i=0;a[i];i++)
		{
			if(a[i]=='W') cout<<"Q";
			else if(a[i]==' ') cout<<" ";
			else if(a[i]=='S') cout<<"A";
			else if(a[i]=='X') cout<<"Z";
			else if(a[i]=='E') cout<<"W";
			else if(a[i]=='D') cout<<"S";
			else if(a[i]=='C') cout<<"X";
			else if(a[i]=='R') cout<<"E";
			else if(a[i]=='F') cout<<"D";
			else if(a[i]=='V') cout<<"C";
			else if(a[i]=='T') cout<<"R";
			else if(a[i]=='G') cout<<"F";
			else if(a[i]=='B') cout<<"V";
			else if(a[i]=='Y') cout<<"T";
			else if(a[i]=='H') cout<<"G";
			else if(a[i]=='N') cout<<"B";
			else if(a[i]=='U') cout<<"Y";
			else if(a[i]=='J') cout<<"H";
			else if(a[i]=='M') cout<<"N";
			else if(a[i]=='I') cout<<"U";
			else if(a[i]=='K') cout<<"J";		
			else if(a[i]=='O') cout<<"I";
			else if(a[i]=='L') cout<<"K";
			else if(a[i]=='P') cout<<"O";
			else if(a[i]=='[') cout<<"P";
			else if(a[i]==';') cout<<"L";
			else if(a[i]==',') cout<<"M";
			else if(a[i]=='.') cout<<",";
			else if(a[i]==']') cout<<"[";
			else if(a[i]=='\'') cout<<";";
			else if(a[i]=='/') cout<<".";
			else if(a[i]=='\\') cout<<"]";
			else if(a[i]=='1') cout<<"`";
			else if(a[i]=='2') cout<<"1";
			else if(a[i]=='3') cout<<"2";
			else if(a[i]=='4') cout<<"3";
			else if(a[i]=='5') cout<<"4";
			else if(a[i]=='6') cout<<"5";
			else if(a[i]=='7') cout<<"6";
			else if(a[i]=='8') cout<<"7";
			else if(a[i]=='9') cout<<"8";
			else if(a[i]=='0') cout<<"9";
			else if(a[i]=='-') cout<<"0";
			else if(a[i]=='=') cout<<"-";
		}
		cout<<endl;
	}	
}

Heist

地址

黄队是一个刷题爱好者,显然,这是一个大佬该有的风范! 黄队的电脑中存着他所有解过的题目,这些题目都是从x开始标号的连续升序列,例如,如果 x = 4 并且总共有 3 个题在文件夹中,那么文件夹中的键盘编号就为 4, 5, 6,如果 x = 10 并且总共有 7 道题,那么题目编号就为 10, 11, 12, 13, 14, 15, 16。 危机! 电脑中毒! 他只剩下n个题目了,分别为a1,a2,…,an,黄队不记得最开始的题目总数(强大!)和开始的标号x了,他想知道最小损失的题目有多少(好止损再做回来!)?

input

第一行是一个整数 n (1≤n≤1000) — 表示电脑被黑之后剩余的题目数。 第二行有n个不同的整数 a1,a2,…,an (0 ≤ ai ≤ 109) — 为剩余题目的一个随机排列。

output

输出最小可能的损失的题目数

example:

Input
4
10 13 12 8
Output
2
Input
5
7 5 6 4 8
Output
0

Time limit —— 1000 ms
Memory limit —— 262144 kB

在第一个样例中, 如果 x=8 那么最少丢失的题数就是 2。其中标号为 9 和 11 的题丢失了。 在第二个样例中, 如果 x=4 那么最少可能就是没有被偷。

代码:

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin>>n;
	//找最大找最小,最大-最小-n+1就是我们中间缺失的数 
	int mx=-1e9,mn=1e9;
	for(int i=0;i<n;i++)
	{
		int x;
		cin>>x;
		mx=max(x,mx);
		mn=min(x,mn);
	}
	cout<<mx-mn+1-n<<endl;
}

E

地址

输入两个n行m列的矩阵,求它们的矩阵和

input

第一行是两个整数n和m,表示矩阵的行和列,0<n,m<=100
接下来n行,每行m个元素,表示第一个矩阵
接下来n行,每行m个冤死,表示第二个矩阵
output

输出两个矩阵的和

example:

3 3
1 2 3
1 2 3
1 2 3
1 2 3
4 5 6
7 8 9

2 4 6
5 7 9
8 10 12

Time limit —— 1000 ms
Memory limit —— 262144 kB

#include<iostream>
using namespace std;
const int N=1e3+10;
int a[N][N];
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			cin>>a[i][j];
		}
	}
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			int x;
			cin>>x;
			a[i][j]+=x;
		}
	}
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			cout<<a[i][j]<<" ";
		}
		cout<<endl;
	}
}

Find The Multiple

地址

在2100年科学家发现了平行宇宙,但是新发现的Earth2的世界中所有数字都是由0和1组成的十进制数,如果从我们的世界穿越到Earth2,数字将发生一些变化,例如:一个正整数n,将被转化为n的一个非零的倍数m,这个m应当符合Earth2的数字规则。你可以假定n不大于200且m不多于100位。
提示:本题采用Special Judge,你无需输出所有符合条件的m,你只需要输出任一符合条件的m即可。

input

输入包含多组数据,每组数据仅一行,只包含一个正整数n,n==0时输入结束 (1 <= n <= 200).
output

对于输入的每组n,都输出任一符合条件的m。即使有多个符合条件的m,你也只需要输出一个即可。

example:

2
6
19
0

10
100100100100100100
111111111111111111

Time limit —— 1000 ms
Memory limit —— 262144 kB

分析:
就是随便给你一个数,要求你找到这个数的全部由1和0组成的倍数
做法有三种,但是能过的只有两种,分别是dfs,bfs,和暴搜打表,其中bfs回超时,而且题目上说m不超过100位,但是实际上本题的测试数据最大的位数也就19位(ULL),这道题对时间的严谨和对数据的不严谨让我觉得这题有问题
第一种:dfs,因为只有1和0,所以可以深搜
第二种:bfs,和上边同理
第三种:打表,因为n最大不过200,所以可以开一个200的数组,靠暴力循环找到所有数的倍数,然后复制粘贴到代码上,有点投机取巧,不推荐使用
代码:

#include<iostream>
using namespace std;
typedef unsigned long long ull;
int n,flag;
void dfs(int k,ull x)
{
	if(flag||k>=19) return ;//19位返回是为了防止爆ull
	//ull 范围是0~18,446,744,073,709,551,615
	if(x%n==0)
	{
		cout<<x<<endl;
		flag=1;
		return ;
	}
	dfs(k+1,x*10);
	dfs(k+1,x*10+1);
}
int main()
{
	while(cin>>n&&n!=0)
	{
		flag=0;
		dfs(0,1);
	}
}

Prime Path

地址

hh学长酷爱素数,他经常自娱自乐,随机挑选两个四位的素数a,b。
游戏规则是:a可以通过改变某一位上的数字使其变成c,但只有当c也是四位的素数时才能进行这种改变。
hh学长可以很轻松的算出a最少经过多少次变化使其变为b,所以他相信你也可以。
例如:1033 -> 8179
1033
1733
3733
3739
3779
8779
8179
最少变换了6次。

input

第一行输入整数T,表示样例数。 (T <= 100)
每个样例输入两个四位的素数a,b。(没有前导零)
output

对于每个样例,输出最少变换次数,如果无法变换成b则输出"Impossible"。

example:

3
1033 8179
1373 8017
1033 1033

6
7
0

Time limit —— 1000 ms
Memory limit —— 262144 kB

分析:
因为找的是最少变化次数,所以更适合用bfs

代码:

#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
const int N=1e5+10;
bool p[N];//因为限制是4位数,所以完全可以先将所有4位数的素数状态标记好 
bool st[N];//标记已经便利过的数,防止走相同的数 
string a,b;
bool prime(int n)//判断是否为素数 
{
	if(n==1) return false;
	for(int i=2;i<=n/i;i++)
	{
		if(n%i==0)
		{
			return false;
		}
	}
	return true;
}
void bfs()
{
	queue<string> q;//存的是string类型的四位数 
	queue<int> q1;//存的是改变的次数 
	q.push(a);
	q1.push(0); 
	int z=(a[0]-'0')*1000+(a[1]-'0')*100+(a[2]-'0')*10+(a[3]-'0');//先将4位数a标记,防止重复找a 
	st[z]=true;
	while(q.size())
	{
		string t=q.front();
		int t1=q1.front();
		q.pop();
		q1.pop();
		if(t==b)
		{
			cout<<t1<<endl;
			return ;
		}
		for(int i=0;i<4;i++)//代表4位数上每一位 
		{
			for(int j='0';j<='9';j++)//将该位改为0~9 
			{
				string tt=t;
				if(t[i]==j) continue;//相同的数直接跳 
				tt[i]=j;//不相同的改 
				int tmp=(tt[0]-'0')*1000+(tt[1]-'0')*100+(tt[2]-'0')*10+(tt[3]-'0');
				if(st[tmp]) continue;//改完后标记过的直接跳 
				if(p[tmp])//没标记且是素数的入队 
				{
					st[tmp]=true;
					q.push(tt);
					q1.push(t1+1);//步数增加 
				}
			}
		}
	}
}
int main()
{
	for(int i=1000;i<=9999;i++)
	{
		p[i]=prime(i);
	}
	int t;
	cin>>t;
	while(t--)
	{
		memset(st,false,sizeof(st));
		cin>>a>>b;
		bfs();
	}	
}

Sum of Consecutive Prime Numbers

地址

我们都知道数字是个好玩意,那么我们想知道一个数字能是否能用若干个(或许是一个)连续的素数之和表示,并且想知道有多少种方法。例如,53 有两种表示方法 5 + 7 + 11 + 13 + 17 和 53。 现在给你一个整数 n,你要告诉他这个数字有多少种不同的连续素数和表示方式。

input

多组数据输入,每行一个数字 n,当 n=0 时结束。 n 在 2 与 10000之间。

output

每个输出占一行,输出对应的答案。

2
3
17
41
20
666
12
53
0

1
1
2
3
0
0
1
2

Time limit —— 1000 ms
Memory limit —— 262144 kB

暴力就行了,把10000以内的所有素数都标记出来
代码:

#include<iostream>
using namespace std;
const int N=1e4+10;
int p[N];
bool prime(int n)
{
	if(n==1) return false;
	for(int i=2;i<=n/i;i++)
	{
		if(n%i==0) return false;
	}
	return true;
} 
int main()
{
	int cnt=0;
	for(int i=2;i<=10000;i++)//标记出所有素数 
	{
		if(prime(i)) p[cnt++]=i;
	}
	int n;
	while(cin>>n&&n!=0)
	{
		int ans=0;
		if(prime(n)) ans++;//如果本身是素数,那么本身就算一种情况 
		int k=0;
		while(p[k]<n)//暴力找连续素数和 
		{
			int res=0;
			for(int i=k;res<=n&&i<cnt;i++)
			{
				if(res==n) ans++;
				res+=p[i];
			}
			k++;
		}
		cout<<ans<<endl;
	}
}

Common Subsequence

地址

HH每次见到小姐姐都十分紧张,为了减缓这种紧张感,他决定尽可能找到自己与小姐姐的共同点。这天,HH凭借自己强大的人格魅力获取了小姐姐的基因片段,同时他也提供了自己的基因片段,现在我们假定,他们的公共点个数为两个片段的最长公共子序列中元素个数,请你来帮帮他吧!

input

多组输入,每行有两个字符串,基因片段长度不超过1000

output

每行一个答案,表示每组数据中他们的公共点个数

abcfbc abfcab
programming contest
abcd mnp

4
2
0

Time limit —— 1000 ms
Memory limit —— 262144 kB

就是一个最长公共子序列的模板题,直接上代码,具体怎么实现的自己搜
代码:

#include<iostream>
#include<string.h>
using namespace std;
const int N=1e3+10;
char a[N],b[N];
int dp[N][N];
int main()
{
	while(cin>>a+1>>b+1)
	{
		memset(dp,0,sizeof(dp));
		int n=strlen(a+1),m=strlen(b+1);
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
				if(a[i]==b[j]) dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
			}
		}
		cout<<dp[n][m]<<endl;
	}
}

最简单的计算机

地址

544在学习完计算机组成原理后设计了一台实验用的计算机,命名为jzg。jzg只能执行简单的六种命令A,B,C,D,E,F;只有二个内存M1,M2;三个寄存器R1,R2,R3。六种命令的含义如下:
命令A:将内存M1的数据装到寄存器R1中;
命令B:将内存M2的数据装到寄存器R2中;
命令C:将寄存器R3的数据装到内存M1中;
命令D:将寄存器R3的数据装到内存M2中;
命令E:将寄存器R1中的数据和寄存器R2中的数据相加,结果放到寄存器R3中;
命令F:将寄存器R1中的数据和寄存器R2中的数据相减,结果放到寄存器R3中。
你的任务是:设计一个程序模拟jzg的运行。

input

有若干组,每组有2行,第一行是2个整数,分别表示M1和M2中的初始内容;第二行是一串长度不超过200的由大写字母A到F组成的命令串,命令串的含义如上所述。

output

对应每一组的输入,输出只有一行,二个整数,分别表示M1,M2的内容;其中M1和M2之间用逗号隔开。
其他说明:R1,R2,R3的初始值为0,所有中间结果都在-231和231之间。

100 288
ABECED
876356 321456
ABECAEDBECAF

388,388
2717080,1519268

Time limit —— 1000 ms
Memory limit —— 262144 kB

又一个模拟题,不过这个还好,不怎么折磨人
代码:

#include<iostream>
#include<string.h>
using namespace std;
long long m1,m2,r1=0,r2=0,r3=0;
int main()
{
	while(cin>>m1>>m2)
	{
		char str[210];
		r1=0,r2=0,r3=0;
		cin>>str;
		int m=strlen(str);
		for(int i=0;i<m;i++)
		{
			char n=str[i];
			if(n=='A') r1=m1;
			if(n=='B') r2=m2;
			if(n=='C') m1=r3;
			if(n=='D') m2=r3;
			if(n=='E') r3=r1+r2;
			if(n=='F') r3=r1-r2;
		}
		cout<<m1<<","<<m2<<endl;
	}
}

Radar Installation

地址

如今我们位于沿海地区,需要安装大炮,使得火力可以覆盖整个区域。海岸线可以视为是无限长的直线。陆地位于海岸线的一侧,海洋位于另一侧。海洋里有若干个岛屿,每个小岛可以视为海洋中的一个点。我们需要在海岸线上安装大炮,每个大炮智能覆盖距离d,因此海洋中的小岛被大炮安装所覆盖的条件是两者间的距离不超过 d 。 我们将海岸线视为 x 轴。海洋的一侧位于 x 轴上方,陆地的一侧位于下方。给定海洋中每个小岛的位置(以xy坐标给出),并给定大炮的覆盖距离,你需要写程序,找出安装大炮的最少数量,使得所有的小岛都被覆盖。

input

输入由多个测试用例组成。每个测试用例的第一行,包含了两个整数 n (1<=n<=1000) 和 d,其中 n 是海洋中小岛的数目,d 是大炮可以覆盖的距离。接下来是 n 行,每行包含了两个整数,表示每个小岛的坐标。每组测试用例之间,以一个空行间隔。
输入终止于包含两个 0 的一行。

output

对于每个测试用例,输出一行,包括测试用例的编号,以及安装大炮所需的最小数量。如果不能全部覆盖,则输出"-1"。

3 2
1 2
-3 1
2 1

1 2
0 2

0 0

Case 1: 2
Case 2: 1

Time limit —— 1000 ms
Memory limit —— 262144 kB

分析:
就是将其转化成区间问题,以海岛的坐标为圆心,以火炮射程为半径画圆,与x轴的两个或一个交点就是火炮可以放置的区间,如下图红色线段

所以问题就转换成给你一堆线段,要求你找到最少的点使得每个线段内都有至少一个点
注意:输入0 0 时结束输入,但这不代表输出种 Case x: y 中的x会停止递增,
代码:

#include<iostream>
#include<cmath>
#include<algorithm>
#include<stdio.h>
using namespace std;
const int N=1e5+10;
struct node
{
	double l,r;
}a[N];
bool cmp(node q,node p)
{
	return q.l<p.l||(q.l==p.l&&q.r>p.r);
}
int main()
{
	int n,s=1;
	double d;
	while(cin>>n>>d)
	{
		if(n==0&&d==0) break;
		int flag=0;
		for(int i=0;i<n;i++)
		{
			int x,y;
			cin>>x>>y;
			if(y>d)
			{
				flag=-1;
			} 
			a[i].l=x-sqrt(d*d-y*y);
			a[i].r=x+sqrt(d*d-y*y);
		}
		if(flag==-1)
		{
			printf("Case %d: -1\n",s++);//即使输入结束s也要递增,不然WA 
			continue;
		}
		sort(a,a+n,cmp);//按左区间排序,找最小的右区间
		int ans=1;
		double my=a[0].r;
		for(int i=0;i<n;i++)
		{
			if(a[i].l<=my)
			{
				my=min(a[i].r,my);
			}
			else
			{
				ans++;
				my=a[i].r;
			}
		}
		printf("Case %d: %d\n",s++,ans);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值