Codeforces Round #704 (Div. 2) ABCD

比赛链接

D题因为一些小错误又FST了

TA:Three swimmers

在这里插入图片描述

题意:有三个游泳的人分别会在0,a,2a,3a,…,0,b,2b,3b,…,以及0,c,2c,3c的时刻位于游泳场的最左端.现在你在p时刻站在泳池最左端,问最快多久之后,会有一个人游到最左端.

idea:模一模就出答案了,注意模完为零的情况就好

ACcode:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;

LL t,a,b,c,p,aa,bb,cc,ans;

int main()
{
	cin>>t;
	while(t--)
	{
		scanf("%lld %lld %lld %lld",&p,&a,&b,&c);
		aa = (a - ( p%a ))%a;
		bb = (b - ( p%b ))%b;
		cc = (c - ( p%c ))%c;
		ans = min( min( aa,bb ) , cc );
		printf("%lld\n",ans);
	}
	return 0;
}

TB:Card Deck

在这里插入图片描述
题意:题目大意为给定一个排列,每次可以将末尾k个数取出并按照原顺序拼接另一个数列,使得另一个数列的字典序最大

idea:因为要求字典序最大,所以每一步的策略即为将前面未选取的数中的最大值放置在最前面,维护一个当前前n项中的最大值t。先从大到小(用结构体记录原来的位置)排序,从最大值开始定位输出当前位置到末尾的数,接着看下一个的位置。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
#define MIN 0xc0c0c0c0
#define INF 0x3f3f3f3f
#define N 101000
using namespace std;

int t,n,a[N],maxx,last;
struct node
{
	int val,xu;
}b[N];
bool cmp(node x,node y)
{
	return x.val>y.val;
}
int main()
{
//	freopen("in.txt","r",stdin);
	cin>>t;
	while(t--)
	{
		a[0] = MIN;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			b[i].val = a[i];
			b[i].xu = i;
		}
		sort(b+1,b+n+1,cmp);
		last = n;
		for(int i=1;i<=n;i++)
		{
			if( b[i].xu <= last )
			{
				for(int j=b[i].xu;j<=last;j++)
				{
					printf("%d ",a[j]);
				}
				last = b[i].xu-1;
			}
		}
		cout<<endl;
	}
	return 0;
}

TC:Maximum width

在这里插入图片描述

题意:给出两个字符串S和T,问S中与T相同的子序列在S中的相邻字母的间隔的最大值。

idea:正向遍历一遍T,求出T的每个字母在S中出现的坐标的最小值,再反向遍历一遍T,求出当前情况下能在S中出现的最大值,最后计算一个字母能在S中出现的最小位置和下一个字母能在S中出现的最大位置之间的差值,结果取最大即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
#define N 1001000
#define INF 0x3f3f3f3f
using namespace std;

int n,m,ans,i,j;
char s[N],t[N];
int a[N],b[N];

int main()
{
	
		ans = 0;
		scanf("%d %d",&n,&m);
		scanf("%s %s",&s+1,&t+1);
		cout<<s;
		int p = n;
		for(i=1,j=1;i<=m;i++)
		{
			while( t[i] != s[j] ) j++;
			if( t[i] == s[j] )
			{
				a[i] = j;
				j++;
			}
		}
		for(i=m,j=n;i>=1;i--)
		{
			while( t[i] != s[j] ) j--;
			if( t[i] == s[j] )
			{
				b[i] = j;
				j--;
			}
		}
		for(i=1;i<m;i++)
		{
			ans = max( b[i+1] - a[i] , ans );
		}
		cout<<ans;
	return 0;
}

TD:Genius’s Gambit

在这里插入图片描述

题意:给定数a,b,k,要求求出两个数x,y,使得x与y在二进制下的0的个数为a,1的个数为b,且x-y在二进制下1的个数为k。不存在这样的x和y就输出No.

idea:比较显然,先特判a=1和b=0这两个情况,此情况下k>0就输出No,不然就输出0。然后考虑x-y后最后还能剩下几个1,推一推会发现最后剩下(a+b-2)个1,判断一下k符不符合要求,符合要求的话,x和y的第一位一定是1,然后y的最后一位一定是1,x的从最后一位倒推的第k位一定是1,剩下的1按顺序放就好,不过这部分的1在x和y的位置一定要相同(这样才能抵消)。

ACcode:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
#define N 1001000
#define INF 0x3f3f3f3f
using namespace std;

int a,b,k,maxx,bb,len;
char s[N],t[N];
int main()
{
	cin>>a>>b>>k;
	if( a==0 || b==1 )
	{
		maxx = 0;
	}
	else
	{
		maxx = (b-1+a)-1;
	}
	if( k > maxx ) 
	{
		cout<<"No";
		return 0;
	}
	len = a+b;
	for(int i=1;i<len;i++)
	{
		s[i] = '0';
		t[i] = '0';
	}
	s[0] = '1';
	t[0] = '1';
	if( b>1 ) t[len-1] = '1';
	if( b>1 ) s[len-1 - k] = '1';
	bb = b-2;
	for(int i=1;i<len;i++)
	{
		if( s[i]!='1' && t[i]!='1' )
		{
			if( bb>0 )
			{
				bb--;
				s[i] = '1';
				t[i] = '1';
			}
		}
	}
	cout<<"Yes"<<endl;
	cout<<s<<endl;
	cout<<t;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值