题目大意
按字母表顺序给出一个初始字符串s,长度为a,你可以任意添加b个字符,之后你的对手将加入a个不同的长度为a的后缀中未出现的字符(字典序加入),询问从l到r中最少出现几个不同字符。
题解
将前a个字符写出,我们可以发现,只有自己写出前面出现过的字符,对手写出的新字符个数才能尽可能少。而为了让区间中不同字符个数少,我们应写相同的字符,由于对手只写后a字符中未出现的字符,所以每次写的字符应是当前最后一个字符。我们可以发现,当写出2*(a+b)个字符后,开始出现循环,所以就能得到答案。
ps:标程似乎挂了,我的程序似乎也挂了。。所以仅供参考。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{
char ch=getchar();int f=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9')
{f=(f<<1)+(f<<3)+ch-'0';
ch=getchar();}
return f;
}
int s[105];bool vis[105],check[105];
int main()
{
int a=read(),b=read(),l=read(),r=read(),tot;
for(int i=1;i<=a;i++)
{
s[i]=i;
}
for(int i=1;i<=b;i++)
{
s[i+a]=s[a];
}
for(int i=b+1;i<=a+b;i++)
{
vis[s[i]]=1;
}
int now=1,pla=a+b;
for(int i=1;;i++)
{
if(!vis[i])
{s[++pla]=i;
vis[i]=1;
}
tot=i;
if(pla==a+b+a)
break;
}
for(int i=a+b+a+1;i<=a+b+a+b;i++)
{
s[i]=s[a+b+a];
}
// for(int i=1;i<=2*a+2*b;i++)
// printf("%d ",s[i]);
if(r-l+1>=2*a+2*b)
{
printf("%d",tot);
return 0;
}
else
{
int x=2*a+2*b;
for(int i=l;i<=r;i++)
{
if(i%x==0)
{
check[s[x]]=1;
}
else check[s[i%x]]=1;
}
int ans=0;
for(int i=1;i<=105;i++)
{
if(check[i])
ans++;
}
printf("%d",ans);
}
}