[BZOJ2081][POI2010]Beads(hash)

来源:互联网 发布:武功山 知乎 编辑:程序博客网 时间:2024/05/17 12:25

题目描述

传送门

题解

hash。
暴力枚举k,然后每次hash。
朴素的求法时间会爆,那么转化成前缀和乱搞。

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<vector>#include<map>using namespace std;#define ll unsigned long longconst int max_n=3e5+5;const int Mod=1e9+7;int n,S;int a[max_n];ll s1[max_n],s2[max_n];ll mi[max_n];int ans,ansk,ANS[max_n];map <ll,bool> hash;inline void Do_It(int k){    int tot=0;    hash.clear();    for (int i=1;i<=n-k+1;i+=k){        if ((n/k)-(i/k)+tot<ans) break;        ll ans1=s1[i+k-1]-s1[i-1]*mi[k];        ll ans2=s2[i]-s2[i+k]*mi[k];        ll major=ans1*ans2;        if (hash[major])          continue;        else{            tot++;            hash[major]=true;        }    }    if (tot>ans){        ans=tot;        ansk=1;        ANS[ansk]=k;    }    else if (tot==ans)      ANS[++ansk]=k;}int main(){    scanf("%d",&n);    for (int i=1;i<=n;++i)      scanf("%d",&a[i]);    S=n+1;    mi[0]=1;    for (int i=1;i<=n;++i)      mi[i]=mi[i-1]*S;    for (int i=1;i<=n;++i)      s1[i]=s1[i-1]*S+a[i];    for (int i=n;i>=1;--i)      s2[i]=s2[i+1]*S+a[i];    for (int i=1;i<=n;++i){        if (ans*i>n) break;        Do_It(i);    }    printf("%d %d\n",ans,ansk);    for (int i=1;i<=ansk;++i)      printf("%d%c",ANS[i]," \n"[i==ansk]);}

总结

学会了基本的东西像这些简单的转化能想到才行啊!

0 0
原创粉丝点击