[BZOJ2081][POI2010]Beads(hash)

11 篇文章 0 订阅

题目描述

传送门

题解

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

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<map>
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 <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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值