题目链接
题意:
一个序列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;
}