2024 年中国大学生程序设计竞赛全国邀请赛(郑州)暨第六届CCPC河南省大学生程序设计竞赛

Problem A. Once In My Life

对于小A而言,数位包含1∼9,并且至少两个数位是d(1≤d≤9)的.十.进.制 .正 .整 .数都是幸运数。
当d=3时,显然1234567890123 是小 A 的幸运数,但987654321 因为数位 3 仅出现了一次而不是
幸运数,998244353 因为缺少数位 1,6,7 而不是幸运数。
现在小A有一个正整数n,并给出正整数d。他想找到正整数k使得二者的乘积n·k是幸运数。你
能用计算机辅助他的计算吗?

输入格式

.
本.题 .测 .试 .点 .包 .含 .多 .组 .数 .据。
第一行,一个正整数T(1≤T ≤3×105),表示数据组数。
对于每组数据:
一行,两个正整数n,d(1≤n≤108,1≤d≤9)。

输出格式

对于每组数据:
输出一行,一个正整数k,满足n·k是幸运数。你需要保证k≤2×1010。
样例
standard input
3
1 6
12345678 9
233 2
standard output
1234567896
404
9217006

提示

对于n=1,d=6,可以取k=1234567896,有 n·k=1234567896 为幸运数。
对于n=12345678,d=9,可以取 k=404,有 n·k=4987653912 为幸运数。
对于n=233,d=2,可以取k=9217006,有 n·k=2147562398 为幸运数。

实现代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
	int n,d;
	cin>>n>>d;
	int l=to_string(n).size();//算出n的位数,后用于添加预留位
	int ans=(1234567890*1ll+d);//满足条件的最小数
	ans=ans*pow(10,l);//制造预留位
	ans=(ans+n)/n;//加上n,除以n,得到结果
	cout<<ans<<'\n';
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int t;
	cin>>t;
	while(t--)	solve();
	return 0; 
}

Problem B. 扫雷 1

T0xel 喜欢玩扫雷,但是他玩的扫雷游戏有名为“地雷探测器”的特殊道具。
具体来说,T0xel 会进行n轮扫雷。每轮扫雷开始之前,T0xel会获得1枚扫雷币。扫雷币在每轮扫
雷结束后不会回收,可以保留至下一轮扫雷。T0xel知道,在第i轮(1≤i≤n)扫雷中,花费ci 枚扫
雷币可以购买一个地雷探测器,清除地图中的一个雷。地雷探测器在一轮扫雷中可以购买任意次。
现在T0xel 想知道,在这n轮扫雷中最多能购买多少个地雷探测器呢?

输入格式

第一行,一个正整数n(1≤n≤2×105),表示扫雷轮数。
第二行,n个正整数c1,c2,…,cn(1≤ci ≤109)。

输出格式

一行,一个非负整数,表示答案。
样例
standard input
6
3 2 5 3 4 3
2
standard output
5
6 3 3 4 2
2
5
7 6 5 9 8
0

提示

对于第一个样例,T0xel 可以选择在第2轮与第6轮扫雷中各购买一个地雷探测器。具体过程如下:
• 获得1枚扫雷币,目前有1枚扫雷币。第1轮扫雷开始,不购买地雷探测器。
• 获得1枚扫雷币,目前有2枚扫雷币。第2轮扫雷开始,购买一个地雷探测器,目前有0枚扫雷币。
• 获得1枚扫雷币,目前有1枚扫雷币。第3轮扫雷开始,不购买地雷探测器。
• 获得1枚扫雷币,目前有2枚扫雷币。第4轮扫雷开始,不购买地雷探测器。
• 获得1枚扫雷币,目前有3枚扫雷币。第5轮扫雷开始,不购买地雷探测器。
• 获得1枚扫雷币,目前有4枚扫雷币。第6轮扫雷开始,购买一个地雷探测器,目前有1枚扫雷币。
对于第二个样例,T0xel 可以选择在第5轮扫雷中购买两个地雷探测器。
对于第三个样例,T0xel 无法在这5轮扫雷中购买地雷探测器。

实现代码

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int w[N];
int main()
{
	int n,mi=INT_MAX;
	cin>>n;
	for(int i=1;i<=n;i++)cin>>w[i];
	for(int i=n;i>=1;i--)
	{
		mi=min(mi,w[i]);
		w[i]=mi;
		//倒序最小赋值
	}
	int t=0,ans=0;
	for(int i=1;i<=n;i++)
	{
		t++;//此时拥有的钱
		if(w[i]<=t)//达到购买所需的钱就买
		{
			int tt=t/w[i];
			ans+=tt;
			t=t-tt*w[i];
		}
	}
	cout<<ans;
	return 0;
}

Problem F. 优秀字符串

小A认为,一个字符串S是优秀字符串,当且仅当:
• S 的长度|S|恰好为5;
• S 的第三个字符与第五个字符相同;
• S 的前四个字符互不相同。
例如henan 是优秀字符串,但query、problem、queue 不是,因为:
• query 的第三个字符为e,而第五个字符为y;
• problem 的长度不为 5;
• queue 的前四个字符中u出现了两次。
现在,小A有n个仅包含英文字母与数字的字符串S1,S2,…,Sn,请你帮小A求出这些字符串中
优秀字符串的数量。

输入格式

第一行,一个正整数n(1≤n≤105),表示字符串的数量。
接下来n行,每行一个仅包含英文字母与数字的字符串Si。保证∑|Si|≤2× 105。

输出格式

一行,一个整数,表示给定字符串中优秀字符串的数量。
样例
standard input
4
henan
query
problem
queue
1
standard output

实现代码

//签到题按照题意输出
#include<bits/stdc++.h>
using namespace std;
string s;
int main()
{
	int t,ans=0;
	cin>>t;
	while(t--)
	{
		s.clear();
		cin>>s;
		if(s.size()==5)
		{
			if(s[2]==s[4])
			{
				int f=0;
				for(int i=0;i<3;i++)
				{
					for(int j=i+1;j<4;j++)
					{
						if(s[i]==s[j])
						{
							f=1;
							break;
						}
					}
					if(f==1)	break;
				}
				if(f==0)	ans++;
			}
		}
	}
	cout<<ans;
	return 0;
}

Problem H. 随机栈

Toxel 获得了一个随机的 “栈”。这个栈可被视为一个 .多 .重 .集 S,从一个非空的随机栈 S 中取出一个
元素时,有可能从中取出任何一个元素,其中每个元素被取出的概率是相等的。取出该元素后,该元素会
从集合中删除。以{1,2,2} 为例,有 1
3 的概率取出1,使得集合变为{2,2},有 2
3 的概率取出2,使得集
合变为{1,2}。每次取出元素的事件相互独立。
Toxel 正在对这个集合做一些操作。集合初始时为空,它总共进行了2n次操作,其中n次操作为插
入,n次操作为取出。现在,Toxel告诉了你它操作的顺序以及每次插入的数,且保证每次取出时,集合
非空。Toxel 想知道,如果把每次取出的数排成一个序列,那么这个序列递增的概率是多少?这里,递增
的严格定义是:取出数列的每一项(除最后一项).小.于.等 .于它的后一项。
由于答案可能不是整数,为了方便计算,你只需要求出这个值对998244353取模的结果。

输入格式

第一行包含一个整数n(1≤n≤2×105)。
第二行包含2n个整数a1,a2,…,a2n(−1≤ai ≤n),表示 Toxel 操作的序列。其中,若0≤ai ≤n,
表示Toxel 向集合中插入了ai;否则ai=−1,表示Toxel从集合中取出了一个元素。数据保证取出元素
时,集合非空;保证插入和取出操作的次数分别为n。

输出格式

输出一行一个整数,表示答案对998244353取模的结果。
样例
standard input
2
1 2-1-1
3
1 2-1-1 1-1
4
1-1 2-1 3-1 4-1
standard output
499122177
0
1

提示

正式地说,答案对998244353 取模表达了如下含义。令M =998244353,可以证明答案可表示为
既约分数 p/q,其中p和q均为整数,且q ̸≡0 (modM)。你需要输出p·q−1modM。换句话说,你需要
输出满足0≤x<M 且x·q≡p (modM)的整数x。
对于样例一,可能有以下两种情况:
• 加入1后,集合变成{1},加入2后,集合变成{1,2}。接下来先取出1,这里有 1,2 的概率,接下
来再取出2。这种情况下,取出的序列为1,2,是递增的,概率为 1,2。
• 加入1后,集合变成{1},加入2后,集合变成{1,2}。接下来先取出2,这里有 1, 2 的概率,接下
来再取出1。这种情况下,取出的序列为2,1,不是递增的,概率为 1, 2。有序的概率为 1,2,而2*499122177≡1 (mod 998244353),故答案为 499122177。
对于样例二,2无论如何都会在第二个1前被取出,递增的概率为0。
对于样例三,取出的序列只有1,2,3,4一种情况,递增的概率为1。

实现代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
const int mod=998244353;
int v[N];
int qmi(int a,int b,int p)
{
	int res=1;
	while(b)
	{
		if(b%2==1)	res=res*a%p;
		a=a*a%p;
		b/=2;
	}
	return res;
}
void solve()
{
	priority_queue<int,vector<int>,greater<int>>q;//升队列
	int n,tt=0;cin>>n;
	int fenzi=1,fenmu=1;
	for(int z=0;z<2*n;z++)
	{
		int x;cin>>x;
		if(x!=-1)
		{
			q.push(x);
			v[x]++;//标记该数出现次数
		}
		else if(x==-1)
		{
			int t=q.top();
			if(t<tt)
			{
				fenzi=0;
				break;
			}
			fenzi =fenzi*v[t]%mod;
			fenmu =fenmu * (int)q.size()%mod;//每次输出时更新分子,分母
			v[t]--;//出队标记
			q.pop();//出队
			tt=t;//更新前一位值
		}
	}
	int ans=fenzi*qmi(fenmu,mod-2,mod)%mod;//逆元,费马小定理
	cout<<ans;
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int T;
	T=1;
	while(T--)	solve();
	return 0;
}

Problem J. 排列与合数

小A在2023年河南省CCPC大学生程序设计竞赛的赛场上遇到了一道名为“排列与质数”的题目。
与大多数选手一样,小A并没能在赛场上解决这个棘手的题目。比赛结束后,小A想到了一个与之相关
的题目:排列与合数,可是小A仍然没有能力解决。这个名为“排列与合数”的题目是这样的:
给定一个有且仅有5 位,且各个数位互不相同的十进制正整数n。你可以重新排列n的各个数位,
但需要保证重新排列得到的整数n′ 没有前导零。请问重新排列数位得到的n′ 能否为合数?若能为合数,
请求出一个满足条件的n′。
例如,当n=12345 时,任意排列得到的n′ 均是合数,因此可以任意取n′。当n=13579时,可以
重新排列数位得到合数n′=97531=7×13933。
一个正整数是合数,当且仅当它可以分解为两个不小于2的整数的乘积。
现在,小A带着他的题目来到赛场上求助。你能帮助小A解决这个题目吗?

输入格式

.
本.题 .测 .试 .点 .包 .含 .多 .组 .数 .据。
第一行,一个正整数T(1≤T ≤105),表示数据组数。
对于每组数据:
一行,一个正整数n(104≤n<105),保证n的各个数位互不相同。

输出格式

对于每组数据:
输出一行,一个整数。若能重新排列n的数位得到合数n′则输出n′,否则输出−1。
样例
standard input
5
12345
12345
12345
12345
13579
standard output
12345
54321
13524
45123
97531

实现代码

//代码1,全排列
#include<bits/stdc++.h>
#include<string>
using namespace std;
const int N=1e5+10;
int pr[N];
int solve()
{
	int f=0;
	string s;
	cin>>s;
	sort(s.begin(),s.end());
	while(next_permutation(s.begin(),s.end()))
	{
		long long x=stoll(s);
		if(pr[x]==1&&s[0]!='0')
		{
			cout<<s<<endl;
			f=1;
			break;
		}
	}
	if(f==0)	cout<<"-1"<<endl;
	return 0;
}
int main()
{
	int t;
	cin>>t;
	for(int i=2;i<=N;i++)
	{
		for(int j=2*i;j<=N;j+=i)
		{
			pr[j]=1;
		}
	}
	while(t--)
		solve();
	return 0;
}
//代码2,规律
#include<bits/stdc++.h>
using namespace std;

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		string s;
		cin>>s;
		if(s[4]=='0'||s[4]=='2'||s[4]=='4'||s[4]=='5'||s[4]=='6'||s[4]=='8')
		//最后一位是这六种数,直接输出
			cout<<s<<'\n';
		else
		{
			for(int i=0;i<5;i++)
			{
				//寻找符合最后一位的数,交换,输出
				if(s[i]=='0'||s[i]=='2'||s[i]=='4'||s[i]=='5'||s[i]=='6'||s[i]=='8')
				{
					swap(s[i],s[4]);
					cout<<s<<'\n';
					break;
				}
			}
		}
	}
	return 0;
 } 

Problem M. 有效算法

给出长度为n的正整数序列{an}和{bn}。对于每个ai(1≤i≤n),进行恰好一次以下操作:
• 将ai 变成满足|ai−x|≤k×bi 的任意整数x。
请你求出最小的非负整数k,使得存在至少一种方法使得操作后序列{an}所有数都相等。

输入格式

本.题 .测 .试 .点 .包 .含 .多 .组 .数 .据。
第一行包含一个正整数T(1≤T ≤1.5×105),表示数据组数。
对于每组数据:
第一行包含一个正整数n(2≤n≤3×105)。
第二行包含n个正整数a1,a2,…,an(1≤ai ≤109)。
第三行包含n个正整数b1,b2,…,bn(1≤bi ≤109)。
保证单个测试点中所有数据的∑n≤3× 105。

输出格式

对于每组数据:
输出一行一个整数,表示答案。
样例
standard input
2
4
8 3 3 5
1 2 3 2
5
4 3 4 5 6
3 1 3 1 1
standard output
2
2

提示

对于样例一,可以令ai 全变为6。
对于样例二,可以令ai 全变为5。

实现代码

//二分法直接找符合条件的答案
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
int a[N],b[N],n;
bool check(long long k)
{
	long long ma=INT_MIN,mi=INT_MAX;
	for(int i=1;i<=n;i++)
	{
		ma=max(a[i]-k*b[i],ma);
		mi=min(a[i]+k*b[i],mi);
	}
	return ma<=mi;
}
void solve()
{
	cin>>n;
	for(int i=1;i<=n;i++)	cin>>a[i];
	for(int i=1;i<=n;i++)	cin>>b[i];
	int l=-1,r=1e9+10;
	while(l+1<r)
	{
		int mid=l+r>>1;
		if(check(mid))	r=mid;
		else	l=mid;
	}
	cout<<r<<'\n';
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int t;
	cin>>t;
	while(t--)
		solve();
	return 0;
}
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值