题意:
给你一个串s,定义f(s)为这个字符串不同子串的数量,h©为f(s+c)-f(s)。问你
题解:
正解好像是扩展KMP,but二分+哈希也能过,就是要调一下哈希的值,23,29,31,101,131,这些我都过不去,最后自暴自弃试了一下1e9+7,它居然就过了,过了。。
首先我们存下所有值出现的位置,由于这里没办法开1e6个vector,那么我们就模拟一个链表,ne[i]表示i这个位置指向的下一个位置,top[i]表示值为i的时候出现的最后一个位置在哪,只要我们循环使用ne数组,就可以实现访问同一个值的每个位置。因为每个值只会被访问一次,所以最坏情况每个位置会被访问一次,加上二分的话,每个位置会被访问log次,也就是nlogn的时间复杂度。
那么对于每个c,我们二分它在前面出现的最长长度,然后按照ne数组去check一遍即可。总时间复杂度:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
好像被卡内存了…那么我们改一下快读缓冲区大小,然后不用unsigned long long ,改用unsigned int ,并且使用双哈希,最后将Pow数组改成快速幂,空间换时间,最终卡了过去。
新的代码在下面
#include<bits/stdc++.h>
using namespace std;
#define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin))
#pragma GCC optimize(2)
#define ri register int
#define ll long long
#define ull unsigned long long
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
if(c==EOF){
x=-1;
return ;
}
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const ll mod=1e9+7;
const int N=1e6+5;
int s[N];
ull p[N],h[N];
int Pow[N];
ull get_h(int l,int r)
{
return h[r]-p[r-l+1]*h[l-1];
}
int ne[N],top[N],n,m;
bool check(int l,int x)
{
int now=top[x];
while(now&&now>=l)
{
ull h1=get_h(n+1-l+1,n+1);
ull h2=get_h(now-l+1,now);
if(h1==h2)
return 1;
now=ne[now];
}
return 0;
}
int main()
{
//freopen("in.txt","r",stdin);
p[0]=Pow[0]=1;
for(int i=1;i<N;i++)
p[i]=p[i-1]*mod,Pow[i]=1ll*Pow[i-1]*3ll%mod;
while(read(n),n!=EOF)
{
read(m);
for(int i=1;i<=m;i++)top[i]=0;
for(int i=1;i<=n;i++)
{
read(s[i]);
ne[i]=top[s[i]],top[s[i]]=i;
}
for(int i=1;i<=n;i++)
h[i]=h[i-1]*mod+(ll)s[i]+80ll;
ll ans=0;
for(ll i=1;i<=m;i++)
{
h[n+1]=h[n]*mod+i+80ll;
if(!top[i])
ans=ans^(1ll*Pow[i]*(n+1)%mod);
else
{
int l=1,r=n,mid,a;
while(r>=l)
{
mid=l+r>>1;
if(check(mid,i))
l=mid+1,a=mid;
else
r=mid-1;
}
ans=ans^(1ll*Pow[i]*(n+1-a)%mod);
}
}
printf("%lld\n",ans);
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin))
#pragma GCC optimize(2)
#define ri register int
#define ll long long
#define ull unsigned long long
#define ui unsigned int
#define pa pair<ui,ui>
inline char nc(){
static char buf[1000005],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,1000005,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
if(c==EOF){
x=-1;
return ;
}
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const pa mod={13331,31};
const int N=1e6+5;
int s[N];
pa p[N],h[N];
const ll mm=1e9+7;
ll qpow(ll a,ll b){ll ans=1;for(;b;b>>=1,a=a*a%mm)if(b&1)ans=ans*a%mm;return ans;}
pa get_h(int l,int r)
{
return (pa){h[r].first-p[r-l+1].first*h[l-1].first,h[r].second-p[r-l+1].second*h[l-1].second};
}
int ne[N],top[N],n,m;
bool check(int l,int x)
{
int now=top[x];
while(now&&now>=l)
{
pa h1=get_h(n+1-l+1,n+1);
pa h2=get_h(now-l+1,now);
if(h1.first==h2.first&&h1.second==h2.second)
return 1;
now=ne[now];
}
return 0;
}
int main()
{
//freopen("in.txt","r",stdin);
p[0]={1,1};
for(int i=1;i<N;i++)
p[i]={p[i-1].first*mod.first,p[i-1].second*mod.second};
while(read(n),n!=EOF)
{
read(m);
for(int i=1;i<=m;i++)top[i]=0;
for(int i=1;i<=n;i++)
{
read(s[i]);
ne[i]=top[s[i]],top[s[i]]=i;
}
for(int i=1;i<=n;i++)
h[i]={h[i-1].first*mod.first+(ll)s[i]+80ll,h[i-1].second*mod.second+(ll)s[i]+80ll};
ll ans=0;
for(ll i=1;i<=m;i++)
{
h[n+1]={h[n].first*mod.first+i+80ll,h[n].second*mod.second+i+80ll};
if(!top[i])
ans=ans^(qpow(3,i)*(n+1)%mm);
else
{
int l=1,r=n,mid,a;
while(r>=l)
{
mid=l+r>>1;
if(check(mid,i))
l=mid+1,a=mid;
else
r=mid-1;
}
ans=ans^(1ll*qpow(3,i)*(n+1-a)%mm);
}
}
printf("%lld\n",ans);
}
return 0;
}