Codeforces GYM101466 题解

132 阅读1分钟

题目链接

A

思路

在线做,把所有数字添加前缀00都变成1919位数字,从高位到低位维护到trie树中,每次插入一个新的数字之前先在trie树上贪心,分别找最大值和最小值。

代码

#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;
const ll INF=0x3f3f3f3f;
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=1E6+2;
int n,tot;
int t[20*N][10];
string ans_max="0",ans_min="999999999999999999999";
void dfs_max(string s)
{
	int rt=0;
	rep(i,0,18)
	{
		int cur=s[i]-'0',maxi=-1,p=-1;
		rep(j,0,9)
		{
			if(t[rt][j] && (cur+j)%10>maxi)
			{
				maxi=(cur+j)%10;
				p=j;
			}
		}
		if(p==-1 && rt)
		{
			ans_max=max(ans_max,s);
			return;
		}
		s[i]=maxi+'0';
		rt=t[rt][p];
	}
	ans_max=max(ans_max,s);
}
void dfs_min(string s)
{
	int rt=0;
	rep(i,0,18)
	{
		int cur=s[i]-'0',mini=INF,p=-1;
		rep(j,0,9)
		{
			if(t[rt][j] && (cur+j)%10<mini)
			{
				mini=(cur+j)%10;
				p=j;
			}
		}
		if(p==-1 && rt)
		{
			ans_min=min(ans_min,s);
			return;
		}
		s[i]=mini+'0';
		rt=t[rt][p];
	}
	ans_min=min(ans_min,s);
}
void insert(string s)
{
	int rt=0;
	rep(i,0,18)
	{
		int cur=s[i]-'0';
		if(!t[rt][cur])
			t[rt][cur]=++tot;
		rt=t[rt][cur];
	}
}
void print(string s)
{
	int flag=0;
	for(auto k:s)
	{
		if(k!='0' || flag)
		{
			flag=1;
			cout<<k;
		}
	}
	if(flag==0)
		cout<<0;
}
int main()
{
	cin>>n;
	rep(i,1,n)
	{
		string s;
		cin>>s;
		while(s.size()<19)
			s='0'+s;
		dfs_max(s);
		dfs_min(s);
		insert(s);
	//	cout<<i<<" ";print(ans_min);cout<<" ";print(ans_max);
		//cout<<endl;
	}
	print(ans_min);
	cout<<" ";
	print(ans_max);
	cout<<endl;
}

E

思路

设第一个串为ss串,第二个串为tt串。二分使用多长tt的前缀,之后用KMP检查一下匹配数即可。

代码

#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;
const ll INF=0x3f3f3f3f;
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 ll N=1E5+10;
ll n,m,k;
ll p[N];
string s,t;
void pre()
{
	ll j=0;
	rep(i,2,m)
	{
		while(j && t[i]!=t[j+1])
			j=p[j];
		if(t[i]==t[j+1])
			++j;
		p[i]=j;
	}
}
ll check(ll x)
{
	ll j=0,ret=0;
	rep(i,1,n)
	{
		while(j && s[i]!=t[j+1])
			j=p[j];
		if(s[i]==t[j+1])
			++j;
		if(j==x)
		{
			++ret;
			j=p[j];
		}
	}
	return ret>=k;
}
void print()
{
	rep(i,1,n)
		cout<<p[i]<<" ";
	cout<<endl;
}
int main()
{
	getline(cin,s);
	n=s.size();
	s=' '+s;
	getline(cin,t);
	m=t.size();
	t=' '+t;
	In(1,&k);
	pre();
	ll l=1,r=m,ans=0;
	while(l<=r)
	{
		ll mid=(l+r)>>1;
		if(check(mid))
		{
			ans=mid;
			l=mid+1;
		}
		else
			r=mid-1;
	}
	if(ans==0)
		puts("IMPOSSIBLE");
	else
		cout<<t.substr(1,ans);
	
}