题意:
一个序列a1,a2,a3…an
选择一个i,然后将序列改成ai,ai-1,…a1,an,an-1,…ai+1
可以进行无数次这样的操作
问:最多有多少不同的序列产生?(答案mod1e9+7)
题解:
如果我们把这个序列当做一个环,我们可以发现无论怎样操作其实都是这个环,只是在环的不同位置中断开
总共有2n中可能,用hash哈希判断是否一样即可
我们将原序列延长一倍
这样是为了方便后边的操作,这样我们就可以从左端1开始向后取n长度的序列,然后hash,存值,如果第一次出现就num++,
一遍操作过后,将整个序列翻转,再进行相同的操作
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=1e6+9;
ull hash1[maxn];
ull base[maxn];
int a[maxn];
map<ull,int>mp;
int n;
ull get_hash(int l,int r)
{
return hash1[r]-hash1[l-1]*base[r-l+1];
}
void hashs()
{
for(int i=1;i<=2*n;i++)
{
hash1[i]=hash1[i-1]*131+(a[i]-'0');
}
}
int main()
{
base[0]=1;
for(int i=1;i<=4e5+9;i++)
{
base[i]=base[i-1]*131;
}
while(cin>>n)
{
mp.clear();
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[n+i]=a[i];
}
hashs();
ull sum=0;
int num=0;
for(int i=1;i<=n;i++)
{
sum=get_hash(i,i+n-1);
if(!mp[sum])
{
num++;
}
mp[sum]=1;
}
reverse(a+1,a+n*2+1);//翻转序列
hashs();
for(int i=1;i<=n;i++)
{
sum=get_hash(i,i+n-1);
if(!mp[sum])
{
num++;
}
mp[sum]=1;
}
printf("%d\n",num);
}
return 0;
}