CSP-J 复赛 模拟题7 and 解析

1.超级素数:

题目描述

素数,又称质数,是指除 11 和其自身之外,没有其他约数的正整数。例如 2,3,5,132,3,5,13 都是素数,而 4,9,12,184,9,12,18 则不是。特别地,规定 11 不是素数(因此自然数的质因数分解就是唯一的)。

如果一个数字的任意前缀所对应的数字都是一个素数,那么我们称这个数字是一个超级素数,例如:

233233是一个超级素数,因为它的三个不同的前缀2,23,2332,23,233都是素数。

而457457本身虽然是一个素数,但是它的前缀4,454,45却不是素数,所以457457不是一个超级素数。

现在给出一个范围[l,r],请你求出在这个范围内所有的超级素数。

输入格式

输入仅一行,两个整数l,r表示题目所给的范围。

输出格式

输出所有在[l,r]范围内的超级素数,每两个数字之间用空格隔开。

输入输出样例

输入 #1

6 30
 

输出 #1

7
23
29

 

输入 #2

20000 30000
 

输出 #2

23333
23339
23399
23993
29399
 

说明/提示

样例解释:

在6∼306∼30范围内的素数有7,11,13,17,19,23,297,11,13,17,19,23,29,但11,13,17,1911,13,17,19由于包含前缀11,而11不是质数,所以这四个数字都不是超级素数,剩余的7,23,297,23,29则满足超级素数的性质。

数据范围:

对于30%30%的数据,保证1≤l≤r≤100.

对于100%的数据,保证1≤l≤r≤5⋅104,且范围内一定有解。

此题为水题,不讲解

根据无解析写代码1:

#include <bits/stdc++.h>
using namespace std;
int l,r,a[50005];
int main()
{
	cin >> l >> r;
	for(int i = l;i <= r;i++)
	{
		int x = i;
		bool flag = true;
		while(x > 0)
		{
			if (x == 1)
			{
				flag = false;
				break;
			}
			for(int j = 2;j < x;j++)
			{
				if (x % 2 == 0)
				{
					flag = false;
					break;
				}
				if (x % j == 0)
				{
					flag = false;
					break;
				}
			}
			if (flag == false)
				break;
			x /= 10;
		}
		if (flag)
			cout << i << "\n";
	}
	return 0;
}

2.点球大战:

题目描述

2024奥运会将要来临,作为世界第一运动,足球也逃不过被出城题目的命运。

现在需要你来模拟一场惊险刺激的点球大战,假设对阵的双方为A和B,点球大战中,双方会按照ABABABABAB的顺序要罚点球,点球罚进则本队加一分,没有罚进也不会扣分。

判断点球大战胜负的规则为得分多者获胜,而如果在某一队罚玩某一球之后,当前双方比分已经使得无论之后的罚球结果如何都不会影响比赛的结果,则此时比赛结束。

现在,给出接下来双方1010个点球的结果,你需要判断点球大战会在第几球时结束,或指出1010球之内两队无法分出胜负。

输入格式

输入第一行,一个整数T表示多组数据。

接下来T行,每行一个长度为1010,且仅由0,10,1构成的字符串,其中第i个字符表示第i次点球的结果,11表示罚进,00表示没有罚进。

输出格式

输出共T行,每行一个整数,表示点球大战会在第几回合结束;如果1010次点球之后没有分出胜负,则输出−1−1。

输入输出样例

输入 #1

3
1111111111
1111111110
0101011010
 

输出 #1

-1
10
6

说明/提示

样例解释:

对于第一组数据,双方在前10轮一直打平,无法判断胜负。

对于第二组数据,双方在前8轮一直打平,第9轮A队罚进而第10轮B队没有罚进导致输球,所以在第1010回合才能决出胜负。

数据范围:

对于100%的数据,保证n≤100.

直接在循环里每次算出A的值和B的值,然后回合减减
接着判断a - b > rb || b - a > ra     如果是true,就输出i+1  flag标记为0

最后flag=1时,输出-1

根据解析写代码2:

#include <bits/stdc++.h>
using namespace std;
int n,ta,tb;
string s;
int main()
{
	cin >> n;
	while(n--)
	{
		int a = 0,b = 0,ra = 5,rb = 5;
		bool flag = true;
		cin >> s;
		for(int i = 0;i < 10;i ++)
		{
			if (i % 2 == 0)
			{
				a += (s[i] == '1');
				ra--;
			}
			else
			{
				b += (s[i] == '1');
				rb--;
			}
			if (a - b > rb || b - a > ra)
			{
				cout << i + 1 << "\n";
				flag = false;
				break;
			}
		}
		if (flag)
			cout << "-1\n";
	}
	return 0;
} 

3.生成序列:

题目描述

数列 a 最开始只有一个数 11,你可以进行若干次操作,每次操作你可以选取 k 个数(k 无限制,小于等于 a 的大小即可),将这 k 个数的和放入 a 的任意一个位置。

给定一个长度为 n 的序列 c,你需要回答 a 能否在进行若干次操作后转为 c。

输入格式

  • 第一行,一个正整数T表示多组数据。

接下来T组数据,每组数据分两行:

  • 每组数据第一行,一个整数n表示需要生成的序列长度。

  • 每组数据第二行,n个整数1,2,...,c1​,c2​,...,cn​表示需要生成的序列。

输出格式

输出共T行,每行表示对一组数据的回答,YES表示可以得到,NO表示无法得到.

输入输出样例

输入 #1

4
5
5 1 3 2 1
5
7 1 5 2 1
3
1 1 1
5
1 1 4 2 1
 

输出 #1

YES
NO
YES
YES
 

说明/提示

样例解释:

对于第一组数据,可以按照如下过程生成序列c:

{1}→{1,1}→{1,2,1}→{1,3,2,1}→{5,1,3,2,1}{1}→{1,1}→{1,2,1}→{1,3,2,1}→{5,1,3,2,1}

对于第二组数据,按照如下过程:

{1}→{1,1}→{1,2,1}{1}→{1,1}→{1,2,1}之后无法得到下一个数字55,所以无法得到c序列。

数据范围:

对于30%的数据,保证n≤20.

对于50%的数据,保证n≤10^2,ci​≤10^2.

对于80%的数据,保证n≤10^4,ci​≤10^4.

对于100%的数据,保证T≤10,n≤10^5,∑n≤2⋅10^5,1≤ci​≤10^5.

先把a数组排序好后,判断如果a[i]>前i项的值,就是NO

根据解析写代码3:

#include <bits/stdc++.h>
using namespace std;
long long a[101010];
int main(){
	int t;
	cin>>t;
	int n;
	while(t--){
		bool flag=0;
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i];
		}
		
		sort(a+1,a+1+n);
		long long ans=a[1];
		if(a[1]!=1){
			cout<<-1<<'\n';
			continue;
		}
		for(int i=2;i<=n;i++){
			 
			if(a[i]>ans){
				flag=1;
				break;
			}
			ans+=a[i];
		}
		if(flag==0){
			cout<<"YES\n";
		} else{
			cout<<"NO\n";
		}
	}
	return 0;
} 

4.方程求解:

题目描述

小明很喜欢解方程。

这一天,小明的数学老师给了他一个看起来很复杂的方程:

a×x1^2​+b×x2^2​+c×x3^2​+d×x4^2​=0

在这个方程中,a,b,c,d均为给定的[−50,50]范围内的整数,x1​,x2​,x3​,x4​是待求解的未知量.

请你求出满足上述方程的(x1​,x2​,x3​,x4​)的解的个数,还需要保证xi​是[−100,100]范围内的非零整数。

输入格式

  • 第一行,一个正整数T,表示多组数据

接下来的T行:

  • 每行四个整数a,b,c,d表示方程的系数。

输出格式

输出共T行:

第i行一个整数,表示对于第i个方程,解的个数

输入输出样例

输入 #1

3
1 1 1 1
0 0 0 0
1 2 3 -4
 

输出 #1

0
1600000000
39088
 

说明/提示

数据范围:

对于10%的数据点,保证a,b,c,d均为0.

另有10%的数据点,保证a,b,c,d中有3个数为0.

另有20%的数据点,保证a,b,c,d中有2个数为0.

另有20%的数据点,保证a,b,c,d中有1个数为0.

对其余40%的数据点,仅保证a,b,c,d在[−50,50][−50,50]的范围内。

用4层循环去枚举x1,x2,x3,x4;
然后去判断如果a*i*i+b*j*j+c*k*k+d*x*x==0   ans++;
最后输出ans;

根据解析写代码4:

#include <bits/stdc++.h>
using namespace std;
int main(){
	int t;
	cin>>t;
	while(t--){
		int a,b,c,d;
		cin>>a>>b>>c>>d;
		int ans=0;
		for(int i=1;i<=100;i++){
			for(int j=1;j<=100;j++){
				for(int k=1;k<=100;k++){
					for(int x=1;x<=100;x++){
						if(a*i*i+b*j*j+c*k*k+d*x*x==0){
							ans++;
						}
					}
				}
			}
		}
		cout<<ans*16<<'\n';
	}
	return 0;
} 

5.卡牌收集计划:

题目描述

某浣熊为了提振旗下干脆面的销量,联合游戏厂商"真·三国无双"推出了新一轮的集武将卡送好礼活动。

小C作为一个有着严重收集癖的干脆面爱好者,他决定集齐所有的武将卡去兑换奖品;但是某浣熊可不会良心到每一包干脆面中的武将卡都不相同。所以小C决定尽可能多的去购买干脆面,从而用数量抵消概率带来的不确定性。

身为一个还在读初中的三好青年,小C购买干脆面的唯一经济来源就是妈妈给的每天11元的零花钱。但黑心的商店老板会根据商店里还剩多少干脆面的库存量提高售价,以使得自身的利益最大化。

具体来说:在接下来的n天时间里,第i天的干脆面售价为pi​,小C每天都可以使用手里的零花钱购买任意包干脆面(只要当前手中的零花钱足够),或是将当天的零花钱存起来以便日后使用。

现在小C想请智慧的你帮忙制定一个购买计划,以帮助他购买到尽可能多包的干脆面。请你求出小C最多可以购买到多少包干脆面?

输入格式

  • 输入第一行,一个整数n表示接下来n天时间。

  • 输入第二行,n个整数1,2,...,p1​,p2​,...,pn​表示每天的干脆面售价。

输出格式

一个整数,表示小C在这n天时间最多可以购买到多少包干脆面。

输入输出样例

输入 #1

6
3 2 5 3 4 3

输出 #1

2

输入 #2

5
6 3 3 4 2
 

输出 #2

2

输入 #3

5
7 6 5 9 8

输出 #3

0
 

说明/提示

样例解释:
  • 对于第一个样例:

Day1: 获得11元零花钱,总钱数1元,不够买这一天的干脆面;

Day2: 获得11元零花钱,总钱数2元,在当天购买一包干脆面,剩余零花钱00元;

Day3: 获得11元零花钱,总钱数1元,不够买这一天的干脆面;

Day4: 获得11元零花钱,总钱数2元,不够买这一天的干脆面;

Day5: 获得11元零花钱,总钱数3元,不够买这一天的干脆面;

Day6: 获得11元零花钱,总钱数4元,在当天购买一包干脆面。

一共可以购买最多两包干脆面。

  • 对于第二个样例:

在第五天购买两包干脆面为最优的购买方案。

数据范围:

对于20%的数据,保证pi​都是相同的.

对于50%的数据,保证n≤100.

对于80%的数据,保证n≤10^4.

对于100%的数据,保证n≤10^6,1≤pi​≤n.

先把最小值求出来,然后再判断a[i]是否等于最小值 ;
等于时,就算出最多可以购买到包数
不等于时,就攒钱

根据解析写代码5:

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

  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值