bzoj 2081 [Poi2010]Beads hash+调和级数
2081: [Poi2010]Beads
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1003 Solved: 334
[Submit][Status][Discuss]
Description
Zxl有一次决定制造一条项链,她以非常便宜的价格买了一长条鲜艳的珊瑚珠子,她现在也有一个机器,能把这条珠子切成很多块(子串),每块有k(k>0)个珠子,如果这条珠子的长度不是k的倍数,最后一块小于k的就不要拉(nc真浪费),保证珠子的长度为正整数。 Zxl喜欢多样的项链,为她应该怎样选择数字k来尽可能得到更多的不同的子串感到好奇,子串都是可以反转的,换句话说,子串(1,2,3)和(3,2,1)是一样的。写一个程序,为Zxl决定最适合的k从而获得最多不同的子串。 例如:这一串珠子是: (1,1,1,2,2,2,3,3,3,1,2,3,3,1,2,2,1,3,3,2,1), k=1的时候,我们得到3个不同的子串: (1),(2),(3) k=2的时候,我们得到6个不同的子串: (1,1),(1,2),(2,2),(3,3),(3,1),(2,3) k=3的时候,我们得到5个不同的子串: (1,1,1),(2,2,2),(3,3,3),(1,2,3),(3,1,2) k=4的时候,我们得到5个不同的子串: (1,1,1,2),(2,2,3,3),(3,1,2,3),(3,1,2,2),(1,3,3,2)
Input
共有两行,第一行一个整数n代表珠子的长度,(n<=200000),第二行是由空格分开的颜色ai(1<=ai<=n)。
Output
也有两行,第一行两个整数,第一个整数代表能获得的最大不同的子串个数,第二个整数代表能获得最大值的k的个数,第二行输出所有的k(中间有空格)。
Sample Input
21
1 1 1 2 2 2 3 3 3 1 2 3 3 1 2 2 1 3 3 2 1
1 1 1 2 2 2 3 3 3 1 2 3 3 1 2 2 1 3 3 2 1
Sample Output
6 1
2
2
题解:
hash可以O(1)求一个字符串的hash值,然后调和级数分析复杂度即可。
1 #include<cstring> 2 #include<cmath> 3 #include<cstdio> 4 #include<algorithm> 5 #include<iostream> 6 #include<map> 7 #include<vector> 8 9 #define N 1000007 10 #define B 200001 11 #define ll long long 12 13 #define Wb putchar(' ') 14 #define We putchar('\n') 15 #define rg register int 16 using namespace std; 17 inline int read() 18 { 19 int x=0,f=1;char ch=getchar(); 20 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 21 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 22 return x*f; 23 } 24 inline void write(int x) 25 { 26 if(x<0) putchar('-'),x=-x; 27 if (x==0) putchar(48); 28 int num=0;char c[15]; 29 while(x) c[++num]=(x%10)+48,x/=10; 30 while(num) putchar(c[num--]); 31 } 32 33 unsigned ll mul[N],s1[N],s2[N]; 34 int n,mx; 35 int a[N]; 36 map<unsigned ll,bool>mp; 37 vector<int>k; 38 39 unsigned ll gethash(int l,int r) 40 { 41 unsigned ll t; 42 if (l<=r) t=s1[r]-s1[l-1]*mul[r-l+1]; 43 else t=s2[r]-s2[l+1]*mul[l-r+1]; 44 return t; 45 } 46 void solve(int x) 47 { 48 if(mx*x>n) return; 49 int ans=0; 50 mp.clear(); 51 for(int i=1;i<=n;i+=x) 52 if(i+x-1<=n) 53 { 54 unsigned ll t=gethash(i,i+x-1)*gethash(i+x-1,i); 55 if (mp[t]) continue; 56 else ans++; 57 mp[t]=1; 58 } 59 if(ans>mx) mx=ans,k.clear(); 60 if(ans==mx) k.push_back(x); 61 } 62 int main() 63 { 64 n=read(); 65 for (int i=1;i<=n;i++) a[i]=read(); 66 mul[0]=1;for (int i=1;i<=n;i++) mul[i]=mul[i-1]*B; 67 for(int i=1;i<=n;i++) 68 s1[i]=s1[i-1]*B+a[i]; 69 for(int i=n;i>=1;i--) 70 s2[i]=s2[i+1]*B+a[i]; 71 for(int i=1;i<=n;i++)solve(i); 72 printf("%d %lu\n",mx,k.size()); 73 for(int i=0;i<k.size();i++) 74 { 75 write(k[i]); 76 if (i<k.size()-1) Wb; 77 } 78 }