[bzoj2081][POI2010]KOR-Beads(hash)

题目:

我是超链接

题解:

这么奇怪的进制(乱打的),他们的乘积能相同的话正过来倒过来就可以判断相等了
这样做还有一个附带好处就是hash值不用乘/除一些奇奇怪怪的数字来保证相等,反正lz觉得sort一下很麻烦呀

代码:

#include <cstdio>
#include <iostream>
#include <map>
#define ull unsigned long long
using namespace std;
const int N=2e5;
const ull p=1300000001ull;
ull mi[N+5],H1[N+5],H2[N+5];
int a[N+5],ans[N+5];
map<ull,bool>hash;
int main()
{
    int n,i,j;
    scanf("%d",&n);
    for (i=1;i<=n;i++) scanf("%d",&a[i]);
    mi[0]=1;for (i=1;i<=n;i++) mi[i]=mi[i-1]*p;
    for (i=1;i<=n;i++) H1[i]=H1[i-1]*p+a[i];
    for (i=n;i>=1;i--) H2[i]=H2[i+1]*p+a[i];
    int cnt=0,maxx=0;
    for (i=1;i<=n;i++)
      if (n/i<maxx) break;
      else
      {
        hash.clear();
        int tot=0;
        for (j=i;j<=n;j+=i)
        {
            ull ans1=H1[j]-H1[j-i]*mi[i];
            ull ans2=H2[j-i+1]-H2[j+1]*mi[i];
            ull ans3=ans1*ans2;
            //if (hash[ans3]) continue;
            if (hash.count(ans3)) continue;
            hash[ans3]=1;
            tot++;
        }
        if (tot>maxx)
        {
            maxx=tot;
            cnt=0;
            ans[++cnt]=i;
        }
        else if (tot==maxx) ans[++cnt]=i;
      }
    printf("%d %d\n",maxx,cnt);
    for (i=1;i<=cnt;i++) 
      printf("%d ",ans[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值