[BZOJ2081][POI2010]Beads(hash)

题目描述

传送门

题解

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

代码

#include
#include
#include
#include
#include
#include
using namespace std;
#define ll unsigned long long

const 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 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)+totbreak;

        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]);
}

总结

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

你可能感兴趣的:(题解,hash)