Codeforces Round #704 (Div. 2) 题解

88 阅读2分钟

A

思路

分别找到小于ppa,b,ca,b,c的最大的倍数,取其与pp差的最小值即可。

代码

#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll> 
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		printf("%lld ",va_arg(lis,ll));
}
void solve()
{
	ll a,b,c,p;
	In(4,&p,&a,&b,&c);
	ll pa=(p+a-1)/a*a;
	ll pb=(p+b-1)/b*b;
	ll pc=(p+c-1)/c*c;
	ll ans=min(pa-p,min(pb-p,pc-p));
	Out(1,ans);
	
}
int main()
{
	int _;
	cin>>_;
	while(_--)
	{
		solve();
	}
}

B

思路

最优解必然是让字典序尽量大。证明:

设最终数组为a,且对任意i[1,n1]:ai>ai+1如果交换其中的ak,ak+1,其他位置对答案的贡献不会改变,所以只考虑这两个位置。最初贡献为nniak+nni1ai+1,交换后贡献为nniai+1+nni1ai做差后得到前者大于后者。设最终数组为a,且对任意i\in[1,n-1]:a_i>a_{i+1}。\\ 如果交换其中的a_k,a_{k+1},其他位置对答案的贡献不会改变,所以只考虑这两个位置。\\ 最初贡献为n^{n-i}a_k+n^{n-i-1}a_{i+1},交换后贡献为n^{n-i}a_{i+1}+n^{n-i-1}a_i。\\ 做差后得到前者大于后者。

代码

#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll> 
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		printf("%lld ",va_arg(lis,ll));
}
const int N=1E5+10;
ll n;
ll a[N],pos[N];
void solve()
{
	In(1,&n);
	rep(i,1,n)
		pos[i]=0;
	rep(i,1,n)
	{
		In(1,&a[i]);
		pos[a[i]]=i;
	}
	ll cur=n;
	for(int i=n;i>=1;--i)
	{
		if(pos[i]<=cur)
		{
			ll tmp=pos[i];
			rep(j,pos[i],cur)
			{
				Out_(1,a[j]);
				pos[a[j]]=LLM;
			}
			cur=tmp-1;
		}
	}
	puts("");
}
int main()
{
	int _;
	cin>>_;
	while(_--)
	{
		solve();
	}
}

C

思路

找出tt中每个单词可以匹配的最靠左的位置lil_i及最靠右的位置rir_i。答案就是max(ri+1li)max(r_{i+1}-l_i)

代码

#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll> 
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		printf("%lld ",va_arg(lis,ll));
}
const int N=2E5+10;
ll n,m;
ll l[N],r[N];
int main()
{
	string s,t;
	In(2,&n,&m);
	cin>>s>>t;
	s=' '+s;
	t=' '+t;
	ll cur=1;
	rep(i,1,n)
	{
		if(s[i]==t[cur])
		{
			l[cur]=i;
			++cur;
		}
	}
	cur=m;
	for(int i=n;i>=1;--i)
	{
		if(s[i]==t[cur])
		{
			r[cur]=i;
			--cur;
		}
	}
	ll ans=0;
	rep(i,1,n-1)
	{
		ans=max(ans,r[i+1]-l[i]);
	}
	Out(1,ans);
}

D

思路

对于xx串,把所有11都放在最前面,只考虑对yy串的构造。对于kak\leq a的情况,yy串前面用1111000011\cdots 1100\cdots 00补齐,其中00kk位,再接上一个11即可。对于k>ak>a的情况,考虑在前一种的基础上,将倒数第二个11右移,就又多出一个11,再将倒数第三个11右移,以此类推。显然对于k>a+b2k>a+b-2的情况无解。

代码

#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll> 
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
	va_list lis;
	va_start(lis,_);
	while(_--)
		printf("%lld ",va_arg(lis,ll));
}
int main()
{
	ll a,b,k;
	In(3,&a,&b,&k);
	if((k>a && k>a+b-2) || (b==1 && k) || (a==0 && k))
	{
		puts("No");
		return 0;
	}
	puts("Yes");
	rep(i,1,b)
		printf("1");
	rep(i,1,a)
		printf("0");
	puts("");
	if(k<=a)
	{
		rep(i,1,b-1)
			printf("1");
		rep(i,1,k)
			printf("0");
		printf("1");
		rep(i,1,a-k)
			printf("0");
	}
	else
	{
		rep(i,1,a+b-k-1)
			printf("1");
		printf("0");
		b=k-a;
		rep(i,1,b)
			printf("1");
		rep(i,1,a-1)
			printf("0");
		puts("1");
	}
}