佳木斯集训Day1考试

嘿嘿我又来了 这么长时间有没有想我啊 显然没有
话不多说直接上题

T1

优美的数字

题目描述
题目背景: Duan2baka喜欢25以及所有25的倍数
Duan2baka实在是太喜欢25啦,他认为世界上只有25和25的倍数是优美的,这天在上课的时候,老师在黑板上写出了一串数字,Duan2baka却只一心想着25,他想将这一串数字变成25的倍数,但是老师告诉他每次只能交换这串数字上相邻的两个数字,Duan2baka想知道,如果自己将这串数字变成25的倍数,那么最少需要交换几次?
输入
输入一个整数n,表示老师写在黑板上的那串数字

输出
输出包含一个整数为Duan2baka将这串数字变成25的倍数所需要交换的最少次数,特别的,如果无法将这串数字通过交换变成25的倍数,那么输出-1。

样例输入
【样例 1 输入】
705
【样例 2 输入】
5071
【样例 3 输入】
5134689
样例输出
【样例 1 输出】
1
【样例 2 输出】
4
【样例 3 输出】
-1
提示
经过交换的最后结果不能出现前导0,如样例1,750是合法的交换结果,而075是不合法的结果
对于20%的数据,n≤1000。
对于50%的数据,n≤1e10。
对于100%的数据,n≤1e18。

首先这题我们应该先知道 所有25的倍数尾数都是00 25 50 75
所以只要枚举每种情况然后取最小值就好了 然而我蜜汁zz打错没了30分

#include<cstdio>
#include<cstring>
int minn(int a, int b){
    
    return a<b?a:b;}
char ch[20],str[20];
int len,c0,c5,cn,ans=10000,now,num1,num2;
bool check;
int main()
{
    
    
	gets(ch);
	len=strlen(ch);
	strcpy(str,ch);
	for(int i=0;i<len;i++)
	{
    
    
		if(ch[i]=='0')c0++;
		if(ch[i]=='2'||ch[i]=='7')cn++;
		if(ch[i]=='5')c5++;
	}
	if(c0>=2)
	{
    
    
		for(int i=len-1;~i;i--)
		{
    
    
			if(ch[i]=='0'&&num1<2)
			{
    
    
				if(num1==0)now+=(len-1-i);
				if(num1==1)now+=(len-2-i);
				num1++;
			}
		}
		if(ans>now)ans=now;
		now=num1=0;
	}
	if(c0>=1&&c5>=1)
	{
    
    
		for(int i=len-1;~i;i--)
		{
    
    
			if(ch[i]=='0'&&!num1)
			{
    
    
				num1++;
				now+=(len-1-i);
				for(int j=i;j<len-1;j++)ch[j]=ch[j+1];
				ch[len-1]='0';
			}
			if(ch[i]=='5'&&!num2)
			{
    
    
				if(i==0&&ch[1]=='0')
				{
    
    
					for(int j=2;j<len-1;j++)if(ch[j]!='0')
					{
    
    
						now+=j-1;
						break;
					}
					now+=(len-2-i);
				}
				else if(!num1)now+=(len-1-i);
				else now+=(len-2-i);
				num2++;
			}
		}
		if(ans>now)ans=now;
		num1=num2=now=0;
	}
	if(c5>=1&&cn>=1)
	{
    
    
		strcpy(ch,str);
		for(int i=len;~i;i--)
		{
    
    	
			if((ch[i]=='2'||ch[i]=='7')&&!num1)
			{
    
    
				if(i==0&&ch[1]=='0')
				{
    
    
					for(int j=2;j<len-1;j++)if(ch[j]!='0')
					{
    
    
						now+=j-1;
						break;
					}
					now+=(len-2-i);
				}
				else if(!num2)now+=(len-1-i);
				else now+=(len-2-i);
				num1++;
			}
			if(ch[i]=='5'&&!num2)
			{
    
    
				if(i==0&&ch[1]=='0')
				{
    
    
					for(int j=2;j<len-1;j++)if(ch[j]!='0')
					{
    
    
						now+=j-1;
						break;
					}
				}
				now+=(len-1-i);
				num2++;
			}
		}
		if(ans>now)ans=now;
	}
	if(ans==10000)puts("-1");
	else printf("%d\n",ans);
}

T2

优美的数组

题目描述
题目背景:msyzsfq想成为最强大的oier
jmsyzsfq在成为最强大的oier之前,要先学会处理数组,规定两个数组等价时当且仅当这两个数组中最小数的位置是相同的,jmsyzsfq认为两个长度相等的数组是优美的,这时Dilhao给jmsyzsfq出了一个难题,给定两个长度为n的数组a和b,要求出一个最大的q,使得从1到q的区间中a数组中的每一个数组都与b数组中对应位置的数组等价,这下jmsyzsfq可被难住啦,你能给出这个问题的答案么?
输入
输入一个整数n,表示数组的长度,
接下来两行,每行分别输入n个数字,表示a,b两个数组,输入保证a数组或b数组是一个排列,也就是说每个数组中最小值的位置是确定的。
输出
输出包含一个整数q,要求保证从1到q的区间中a数组中的每一个数组都与b数组中对应位置的数组等价,给出最大的q。
样例输入
【样例 1 输入】
2
1 2
2 1
【样例 2 输入】
5
5 3 4 2 1
4 2 3 1 5
样例输出
【样例 1 输出】
1
【样例 2 输出】
4
提示
对于30%的数据,n≤10。
对于50%的数据,n≤1000。
对于 100%的数据,n≤100,000。

用单调栈维护最小值 每进来一个数就总体判一遍
PS:温馨提示 本题说的是1-p中所有的数组 而不是1-p这个数组虽然你看错会顺利地AC

#include<cstdio>
#include<algorithm>
using namespace std;
#define N 1000001
int n,t1,t2,num=1,a[N],b[N],q1[N],q2[N];
inline void read(int &x)
{
    
    
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){
    
    if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){
    
    s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
	x=s*w;
}
int main()
{
    
    
    read(n);
    for(int i=1;i<=n;i++)read(a[i]);
    for(int i=1;i<=n;i++)read(b[i]);
    while(num<=n)
    {
    
    
        while(a[q1[t1]]>a[num]) t1--;
        q1[++t1]=num;
        while(b[q2[t2]]>b[num]) t2--;
        q2[++t2]=num;
        if(q1[1]!=q2[1]) break;
        num++;
    }
    printf("%d",num-1);
}

T3

优美的数对

题目描述
题目背景:jmsyzsfq很喜欢玩自走棋
作为现在最热门的游戏模式,自走棋深深地吸引住了jmsyzsfq,于是jmsyzsfq尝试自己设计一盘自走棋游戏,每局自走棋游戏有n个玩家,并且将会进行m场对战,每场对战将会有两个玩家进行对战,特别的是,每个玩家都有属于自己的等级,jmsyzsfq希望,每场对战的两个玩家是相同的等级以保证游戏公平,但是Dilhao告诉他,这m场对战的玩家等级并不相等,jmsyzsfq决定更改其中一些玩家的等级保证游戏平衡,他想问问你,最少需要修改多少个玩家的等级,才能保证游戏平衡?

输入
第一行包括三个整数n,m,表示玩家数量和对战场数
第二行包括n个整数,表示每个玩家的等级
下面m行,每行2个整数x,y,表示x号和y号玩家将进行对战,保证x不等于y。
输出
输出包含一个整数为最少需要修改等级的玩家数量。
样例输入
【样例1输入】
3 2 3
1 2 3
1 2
2 3
【样例2输入】
3 2 2
1 1 2
1 2
2 1
样例输出
【样例1输出】
2
【样例2输出】
0
提示
对于30%的数据,n,m≤10。
对于50%的数据,n,m≤1000。
对于100%的数据,n,m,k≤100,000,保证玩家等级≤n。

并查集 把所有会的对战对手都弄到一个集合里 每个集合里修改次数就是集合元素个数减去集合中出现最多次数的元素
我写的有点麻烦…

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
inline void read(int &x)
{
    
    
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){
    
    if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){
    
    s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
	x=s*w;
}
int n,m,k,x,y,ans,cnt,tot,now,nowsum,a[100001],arr[100001],com[100001],f[100001],lev[100001];
int find(int x){
    
    return f[x]==x?x:f[x]=find(f[x]);}
void merge(int x, int y)
{
    
    
	x=find(x);y=find(y);
	if(x!=y)f[x]=y;
}
int main()
{
    
    
	read(n);read(m);read(k);
	for(int i=1;i<=n;i++)read(lev[i]);
	for(int i=1;i<=n;i++)f[i]=i;
	for(int i=1;i<=m;i++)
	{
    
    
		read(x);read(y);
		merge(x,y);
	}
	for(int i=1;i<=n;i++)arr[f[i]]++;
	for(int i=1;i<=n;i++)if(arr[i]>1)a[++cnt]=i;
	for(int i=1;i<=cnt;i++)
	{
    
    
		memset(com,0,sizeof(com));
		tot=now=nowsum=0;
		for(int j=1;j<=n;j++)if(f[j]==a[i])com[++tot]=lev[j];
		sort(com+1,com+1+tot);
		for(int j=1;j<=tot;j++)
		{
    
    
			if(com[j]!=com[j-1])
			{
    
    
				if(nowsum>now)now=nowsum;
				nowsum=1;
			}
			else nowsum++;
		}
		if(nowsum>now)now=nowsum;
		ans+=tot-now;
	}
	printf("%d\n",ans);
}

Day1的考试题就是这样 ! 没什么难题但我好像脑子缺点啥只打了210…
一会儿我会把今天的练习题发出来的
有问题可以写到下面的评论区 或者加QQ407694747 我们一起讨论
各路神犇各位大佬请多多指教!

猜你喜欢

转载自blog.csdn.net/dhdhdhx/article/details/97406947
今日推荐