[bzoj2081][哈希]Beads

版权声明:蒟蒻写的..能不能吱一声呀 https://blog.csdn.net/Rose_max/article/details/84536483

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

Sample Output

6 1

2

题解

为了挽救排名来水一篇…
显然发现枚举所有K+段是调和级数的复杂度
于是就可以哈希了
一个串的哈希值设为前面哈希值和后面的哈希值的乘积
开个map什么的玩一玩就行了…
如果朴素哈希的话我被卡了好多发,听说base设为2333有奇效?

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#define LL long long
#define mp(x,y) make_pair(x,y)
using namespace std;
const LL mod=1e9+7;
inline int read()
{
	int f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int stack[20];
const LL base=2333;
LL ha1[210000],ha2[210000],ha3[210000],ha4[210000],temp1[210000],temp2[210000];
LL work1(int l,int r){return (ha1[r]-ha1[l-1]*temp1[r-l+1]%mod+mod)%mod;}
LL work2(int l,int r){return (ha2[l]-ha2[r+1]*temp1[r-l+1]%mod+mod)%mod;}
inline void write(int x)
{
    if(!x){putchar('0');return;}
    int top=0;
    while(x)stack[++top]=x%10,x/=10;
    while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
map<LL,int> mp;
int n,a[210000];
int ans,a1[210000],ln;
int main()
{
	temp1[0]=1;for(int i=1;i<=200000;i++)temp1[i]=temp1[i-1]*base%mod;
	n=read();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=1;i<=n;i++)ha1[i]=(ha1[i-1]*base+a[i])%mod;
	for(int i=n;i>=1;i--)ha2[i]=(ha2[i+1]*base+a[i])%mod;
	for(int i=1;i<=n;i++)
	{
		int ct=0;mp.clear();
		for(int j=1;i*j<=n;j++)
		{
			int lst=i*(j-1)+1,now=i*j;
			LL u1=work1(lst,now)*work2(lst,now)%mod;
			if(!mp[u1])mp[u1]=1,ct++;
		}
		if(ct>ans)ans=ct,a1[ln=1]=i;
		else if(ct==ans)a1[++ln]=i;
	}
	pr1(ans);pr2(ln);
	for(int i=1;i<=ln;i++)pr1(a1[i]);
	puts("");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Rose_max/article/details/84536483