兰州大学第一届『飞马杯』程序设计竞赛(同步赛),签到题ACFHJ

算法 专栏收录该内容
612 篇文章 2 订阅

题号 标题 通过率 我的状态
A ★★比赛新机制★★ 309/1537 通过
(找规律+前缀和维护)
(longlong记得开1e18,我1e15WA了一个多小时)

B ★★体育课排队★★ 1/12 未通过
C ★★生命的游戏★★ 223/624 通过
(直接暴力就行,收尾可以用-1+n%n处理)

D ★★飞马祝福语★★ 4/26 未通过
E ★★序列大团结★★ 0/1 未通过
F ★★飞马分隔符★★ 655/2215 通过
(维护一个字符串和变量累加更新一下)

G ★★糖果魔法阵★★ 2/15 未通过
H ★★温暖的力量★★ 846/2487 通过
(因为要最多质数所以用尽可能小的,所以全部都是2,奇数的话换一个3,特判<=3的时候为-1)

I ★★平形四边行★★ 7/271 未通过
J ★★翻滚吧硬币★★ 126/767 通过
(特判三种情况,,三个圆心构成三角形,余弦定理可以算出角度和弧长,用剩余的弧长去除一下就行, spj不支持longdouble可还行)

K ★★快乐苹果树★★ 1/8 未通过
L ★★星星收集者★★ 0/2 未通过

A. ★★比赛新机制★★

比赛主页

我的提交

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述

最近,AllenAllen 教授研发了一种新的比赛机制,这种比赛机制是 ACPCACPC (Asia ; Collegiate ; Programming ; Contest)(AsiaCollegiateProgrammingContest) 赛制的扩展,简称 AUPCAUPC (Asia ; University ; Programming ; Contest)(AsiaUniversityProgrammingContest)。参赛者为个人参赛(即每人一台电脑),且成绩分为两部分,过题数和罚时。每道题目的罚时 ss 与比赛已经开始的时间(按分钟计) aa 以及该题错误的提交次数(不包括编译错误) bb 有关,即 s=a+b \times 20s=a+b×20。
另外,新赛制规定,每位参赛者必须按一定的顺序循环做题,直到解出全部题目或比赛结束。在比赛开始之前,每位参赛者可以任意选择第一个要做的题目和方向:正序或者逆序,但是中途不能跳题或者改变方向。例如,现在有 A,B,C,D,EA,B,C,D,E 五道题目,参赛者可以选择第一个要做的题目 CC,然后按正序 C,D,E,A,BC,D,E,A,B 的顺序做题,或者按逆序 C,B,A,E,DC,B,A,E,D 的顺序做题,而 C,D,B,A,EC,D,B,A,E 或 C,E,A,B,DC,E,A,B,D 都是不被允许的。

AliceAlice 水平非常高,她总是可以做出所有的题目。现在她想知道,如果已知解决每道题需要花费的时间,那么解决 nn 道题的最少罚时是多少。我们认为比赛时间足够 AliceAlice 解决所有题目,在比赛开始的瞬间 AliceAlice 就开始做题并且所有题目都是一次提交便成功通过。
输入描述:
第一行一个整数 T ; (1 \leq T \leq 5 \times 10^{5})T(1≤T≤5×10
5
),表示测试用例的数量。

对于每组测试用例,第一行一个整数 n ; (1 \leq n \leq 5 \times 10^{5})n(1≤n≤5×10
5
),表示题目的数量;

接下来一行 nn 个整数,第 i ; (1 \leq i \leq n)i(1≤i≤n) 个整数 A_{i} ; (1 \leq A_{i} \leq 5 \times 10^{5})A
i

(1≤A
i

≤5×10
5
),表示解决第 ii 道题需要花费的时间(按分钟计)。

对于全部测试用例,保证 \sum n \leq 5 \times 10^5∑n≤5×10
5

输出描述:
对于每组测试用例,输出一行一个整数表示答案。
示例1
输入
复制
2
5
2 1 5 3 4
10
5 9 3 7 8 1 10 4 6 2
输出
复制
36
277
说明
在第一组测试用例中,AliceAlice 按题目编号 2,1,5,4,32,1,5,4,3 的顺序做题,总罚时最少,为 1+3+7+10+15=361+3+7+10+15=36。
在第二组测试用例中,总罚时最少为 5+7+13+17+27+28+36+43+46+55=2775+7+13+17+27+28+36+43+46+55=277

找找规律
12345
51234
45123
34512
23451
12345

54321
15432
21543
32154
43215
54321

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 6e5+10;
LL a[maxn], pows[maxn], s[maxn];
int main(){
	ios::sync_with_stdio(false);
	int T;  cin>>T;
	while(T--){
		int n;  cin>>n;
		LL sum = 0, ans = 1e18+10;
		s[0] = 0; 
		for(int i = 0; i < n; i++){
			cin>>a[i]; pows[i] = i+1;
			sum += pows[i]*a[i];
			if(i!=0)s[i] = s[i-1];
			s[i] += a[i];
		}
		ans = min(ans, sum);
		for(int i = 0; i < n-1; i++){
			if(i<n-1)sum -= (s[n-1]-s[i]);
			if(i>0)sum -= (s[i-1]);
			sum += (n-1)*a[i];
			ans = min(ans, sum);
		}
		sum = 0;
		for(int i = 0, j = n-1; i <= n-1; i++,j--){
			sum += a[i]*pows[j];
		}
		ans = min(ans, sum);
		for(int i = 0; i < n-1; i++){
			if(i<n-1)sum += (s[n-1]-s[i]);
			if(i>0)sum += (s[i-1]);
			sum -= (n-1)*a[i];
			ans = min(ans,sum);
		}
		cout<<ans<<"\n";
	}
    return 0;
}

C ★★生命的游戏★★

比赛主页

我的提交

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
生命游戏(Conway’s ; Game ; of ; LifeConway

sGameofLife)是英国数学家约翰·何顿·康威在 1970 年发明的一款“零玩家游戏”。

生命游戏的“棋盘”是一个 𝑛 \times 𝑛n×n 的网格,每个网格代表一个“细胞”,每个细胞有两种状态:“生”或“死”。生命游戏每隔一段时间进行一次演变,称为一个“回合”。

在生命游戏中,每个细胞在一个新回合的生与死只取决于它在上一个回合时周围 88 个细胞的存活状态,具体的规则如下:

如果一个死亡的的细胞周围恰好有 33 个活的细胞,那么下一个回合时,这个细胞的状态将转为“生”
如果一个存活的的细胞周围活细胞的数量大于 33 或小于 22,那么下一个回合时,这个细胞的状态将转为“死”
其他情况下,细胞的存活状态不变
特别地,我们规定第 ii 行第 jj 列的细胞为 (i,j)(i,j),且在“棋盘”边缘的细胞在位置上与另一侧循环相连。例如细胞 (n,n)(n,n) 的右侧是细胞 (n,1)(n,1),下方是细胞 (1,n)(1,n)。

CindyCindy 特别喜欢生命游戏,她常常能够在看似毫无规律的生命游戏中发现许多有趣的现象。例如对于某些初始状态,会在若干回合的演变之后再次回到最初的状态,即所有对应位置的细胞状态完全相同,我们便认为该初始状态存在周期。

例如,图 C-1C−1 在进行一次演变之后会变成图 C-2C−2,再进行一次演变后又会重新变为 C-1C−1,其周期为 22。(其中 ★ 代表“生”)

对于一个给定的初始状态,CindyCindy 想知道在 kk 回合之内(包括第 kk 回合)该状态是否存在周期。

输入描述:
第一行一个整数 T ; (1 \leq T \leq 100)T(1≤T≤100),表示测试用例的数量。

对于每组测试用例,第一行两个整数 n,k; (1 \leq n,k \leq 100)n,k(1≤n,k≤100),分别表示棋盘的大小和回合次数;

接下来 nn 行,一个 n \times n n×n 的 0101 矩阵,表示初始状态。其中 11 表示存活,00 表示死亡。
对于全部测试用例,保证 \sum n, \sum k \leq 100∑n,∑k≤100。
输出描述:
对于每组测试用例,输出一行一个字符串,如果存在周期,先在第一行输出 YES,然后在第二行输出第一次出现周期的回合数;如果不存在周期,直接输出一行 NO。
示例1
输入
复制
2
5 2
0 0 0 0 0
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 0 0 0
5 50
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
输出
复制
YES
2
NO
说明
在第一组测试用例中,第一次出现周期的回合数为 22。
在第二组测试用例中,在 5050 回合内初始状态不会出现周期。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 6e5+10;
int a[110][110], b[110][110], c[110][110];
int main(){
	ios::sync_with_stdio(false);
	int T;  cin>>T;
	while(T--){
		int n, k;  cin>>n>>k;
		for(int i = 0; i < n; i++)
			for(int j = 0; j < n; j++)
				{ cin>>a[i][j]; c[i][j]=a[i][j];}
		int flag = 1;
		for(int kk = 1;  kk <= k; kk++){
			for(int i = 0; i < n; i++){
				for(int j = 0; j < n; j++){
					int cc = 0;
					for(int dx=-1; dx<=1; dx++)
						for(int dy=-1; dy<=1;dy++)
							cc += a[(i+dx+n)%n][(j+dy+n)%n];
					cc -= a[i][j];
					b[i][j] = a[i][j];
					if(a[i][j]==0 && cc==3)b[i][j] = 1;
					if(a[i][j]==1 && (cc>3||cc<2))b[i][j] = 0;
				}
			}
			int ok = 1;
			for(int i = 0; i < n; i++){
				for(int j = 0; j < n; j++){
					a[i][j] = b[i][j];
					if(a[i][j]!=c[i][j])ok = 0;
				}
			}
			if(ok==1){
				cout<<"YES\n"<<kk<<"\n";
				flag = 0;
				break;
			}
		}
		if(flag==1)cout<<"NO\n";
	}
    return 0;
}


F. ★★飞马分隔符★★

链接:https://ac.nowcoder.com/acm/contest/16520/F
来源:牛客网

题目描述
FordFord 非常喜欢FeiMa,如果一个字符串中存在一个子序列为FeiMa,FordFord 就会异常兴奋,然而这可能会导致一些无法预料的后果。
子序列为原字符串中删去若干字符,剩余字符相对位置不变形成的序列。例如ac,abcd均是abcd的子序列,而ca则不是abcd的子序列。
为了防止意外发生,你需要将这个字符串 ss 按顺序划分为若干部分 s_{1},s_{2},\ldots,s_{k}s
1

,s
2

,…,s
k

,且 s_{1}+s_{2}+\cdots+s_{k}=ss
1

+s
2

+⋯+s
k

=s(++ 表示字符串的连接),使得每一部分都不包含子序列FeiMa。而每次划分都需要一个“分隔符”,每个“分隔符”都要去商店购买。

现在,你想知道最少需要购买多少个分隔符。
输入描述:
第一行一个整数 T ; (1 \leq T \leq 10^{5})T(1≤T≤10
5
),表示测试用例的数量。
对于每组测试用例,第一行一个整数 n ; (1 \leq n \leq 10^{5})n(1≤n≤10
5
),表示字符串的长度;

接下来一行一个长度为 nn 的字符串 ss。

对于全部测试用例,保证字符串 ss 中仅包含大小写英文字母和数字且 \sum n \leq 10^{5}∑n≤10
5

输出描述:
对于每组测试用例,输出一行一个整数表示答案。
示例1
输入
复制
2
18
FeiMa20210529FeiMa
5
MaFei
输出
复制
2
0
说明
在第一组测试用例中,可将 ss 分为 Fei、Ma20210529Fei、Ma,最少需要 22 个分隔符。
在第二组测试用例中,不需要分隔符。

#include<bits/stdc++.h>
using namespace std;
string cc="FeiMa"; 
int main(){
	ios::sync_with_stdio(false);
	int T;  cin>>T;
	while(T--){
		int n; string s; cin>>n>>s;
		int cur = 0, ans = 0;
		for(int i = 0; i < s.size(); i++){
			if(s[i]==cc[cur]){
				cur++;
				if(cur==5){
					ans++;
					cur = 0;
				}
			}
		}
		cout<<ans<<"\n";
	}
    return 0;
}

H. ★★温暖的力量★★

★★温暖的力量★★
比赛主页

我的提交

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
小时候,HelenHelen 曾感受到一份与众不同的温暖。那份温暖,蕴含着令人重生的力量。即便过去了很久很久,她依然无法忘却。

随着时间的流逝,这份温暖被随机分成了 x ; (x \gt 1)x(x>1) 份。由于温暖之间的羁绊,每份温暖分到的力量都是质数,并且力量总和与原来相同。

为了重新寻回这份温暖,必须知道 xx 最大可能为多少。但是 HelenHelen 思考了很久,也未能如愿。
作为 HelenHelen 的好友,你不想再看到她为此忧伤。因此你需要帮助 HelenHelen 找到这个最大的 xx 值。
输入描述:
第一行一个整数 T ; (1 \leq T \leq 10^{5})T(1≤T≤10
5
),表示测试用例的数量。

对于每组测试用例,输入一行一个整数 s ; (1 \leq s \leq 10^{6})s(1≤s≤10
6
),表示这份温暖最初蕴含的力量。
输出描述:
对于每组测试用例,输出一行一个整数,如果 xx 有解,则输出 xx,否则输出 -1−1。
示例1
输入
复制
2
4
5
输出
复制
2
2
说明
在第一组测试用例中,温暖最多可以被分为 22 份,蕴含的力量分别为 2,22,2。

在第二组测试用例中,温暖最多可以被分为 22 份,蕴含的力量分别为 2,32,3。

#include<bits/stdc++.h>
using namespace std;
int main(){
	ios::sync_with_stdio(false);
	int T;  cin>>T;
	while(T--){
		int x;  cin>>x;
		if(x<=3)cout<<"-1\n";
		else cout<<x/2<<"\n";
	}
    return 0;
}

J. ★★翻滚吧硬币★★

比赛主页

我的提交

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
JackJack 是一个喜欢动脑的孩子,在他的生日这天,他收到了一份神奇的礼物:三枚硬币以及一封信。
信中描述了这样一个情景:任取两枚硬币固定在二维平面上,并让它们恰好相切,用第三枚硬币沿着它们形成的边界进行翻滚,即时刻保证与至少一枚已固定的硬币相切。这样这枚运动的硬币在翻滚了一定的圈数之后,一定会回到原点,即恰好绕了一周。(如此一来,便会出现三种情况:固定 A,BA,B,让 CC 运动;固定 A,CA,C,让 BB 运动;固定 B,CB,C,让 AA 运动)

信里还说,如果 JackJack 能求出运动的硬币翻滚的圈数最少是多少,那么他将会收获一份更大的礼物。JackJack 非常想要这份大礼,但是又不知道如何解决这个难题,因此他向你求助问题的答案。

输入描述:
第一行一个整数 T ; (1 \leq T \leq 10^{5})T(1≤T≤10
5
),表示测试用例的数量。
对于每组测试用例,输入一行三个整数 R_{1},R_{2},R_{3} ; (1 \leq R_{1},R_{2},R_{3} \leq 10^{9})R
1

,R
2

,R
3

(1≤R
1

,R
2

,R
3

≤10
9
),分别表示三枚硬币的半径。
输出描述:
对于每组测试用例,输出一行一个实数表示答案。只要你的答案与标准答案的绝对或相对误差不超过 10^{-9}10
−9
则被认为正确。
在形式上,若你的答案是 aa,标准答案是 bb,那么当且仅当 \displaystyle \frac{|a-b|}{\max(1,|b|)} \leq 10^{-9}
max(1,∣b∣)
∣a−b∣

≤10
−9
时,你的答案才会被判定为正确。

示例1
输入
复制
2
1 2 3
5 5 5
输出
复制
1.841387941165222
2.666666666666667
说明
在第一组测试用例中,固定前两枚硬币,用第三枚硬币绕其边界翻滚一周,圈数最少,约为 1.8413879411652221.841387941165222。
在第二组测试用例中,固定其中任意两枚硬币,用第三枚硬币绕其边界翻滚一周,圈数最少,约为 2.6666666666666672.666666666666667。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 6e5+10;
double PI = 3.14159265358979;
double solve(double r1, double r2, double r3){
	double a = r1+r2, b = r1+r3, c = r2+r3;
	double res = (r2+r3)/r1;
	double s1 = acos((a*a+c*c-b*b)*1.0/2.0/a/c);
	double s2 = acos((b*b+c*c-a*a)*1.0/2.0/b/c);
	double s3 = acos((a*a+b*b-c*c)*1.0/2.0/a/b);
	double t = (s3*r1-s1*r2-s2*r3)/(PI*r1);
	return res+t;
}
int main(){
	//ios::sync_with_stdio(false);
	int T;  cin>>T;
	while(T--){
		int a, b, c;  cin>>a>>b>>c;
		printf("%.15lf\n", min(solve(a,b,c),min(solve(b,a,c),solve(c,a,b)))+1);
	}
    return 0;
}

  • 1
    点赞
  • 6
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值