LOJ6480 「ICPC World Finals 2017」弄虚作假的塔罗占卜 Tarot Sham Boast 题解
一丶前言:
感谢我们的教练 @jzp1025 的口胡证明与官方题解口胡翻译。
二丶思路:
一道结论好题,假设那个长度为
显然,长度为
(一个简单的容斥,应该看看就懂,注意
若
若
可以发现,其实
则
所以我们可以猜到,正解一定跟
实际上,结论是:
我们把每个
感性的证明:
为了方便,假设当前字符串为
假设
(就是
则
略加思考可以发现:
1.所有字符串的
2.
根据这两条结论,我们可以发现
那实际上我们比较的就是所有字符串的
而因为
结束了?不,还要考虑有些
就是在
三丶代码
//Badwaper gg
#include<bits/stdc++.h>
#define inf 1e9
#define eps 1e-6
#define mp make_pair
#define pb push_back
#define re register ll
#define fr first
#define sd second
#define FOR(i,a,b) for(re i=a;i<=b;i++)
#define REP(i,a,b) for(re i=a;i>=b;i--)
#define lowbit(x) (x&(-x))
#define Z(x) (x>=mod?x-mod:x)
#define N 1000010
#define seed 131
#define mod 998244353
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline ll read()
{
char ch=getchar();
ll s=0,w=1;
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
int n,S;
ll H[N],Hash[N];
char s[N];string g[N];
pair<vector<int>,int>t[N];
int main()
{
// freopen("loj6480.in","r",stdin);
// freopen("loj6480.out","w",stdout);
n=read(),S=read();H[0]=1;
FOR(i,1,n)H[i]=1LL*H[i-1]*seed%mod;//要用模数hash,自然溢出被卡了
FOR(i,1,S)
{
scanf("%s",s+1);int len=strlen(s+1);
FOR(j,1,len)g[i]+=s[j];
FOR(j,1,len)Hash[j]=(Hash[j-1]+1LL*s[j]*H[j]%mod)%mod;
vector<int>v;
REP(j,len-1,0)//求border,从大到小插入
{
if(len*2-j>n)continue;
if(1LL*Hash[j]*H[len-j]%mod==(Hash[len]+mod-Hash[len-j])%mod)v.pb(j);
}
t[i]=mp(v,i);
}
sort(t+1,t+S+1);//vector默认从大到小排序
FOR(i,1,S)cout<<g[t[i].second]<<endl;
return 0;
}
如果你觉得这篇题解对你有帮助,那你可以点个赞支持我一下qwq。如果你对题解有任何问题/认为我的题解有任何问题,可以私信/在评论区发出来,当然如果你对我的题解有任何意见/建议也欢迎指出。我会尽我全力把我题解写到最好的qwq