码迷,mamicode.com
首页 > 其他好文 > 详细

[CF1045B]Space Isaac

时间:2019-02-17 22:14:38      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:ref   方法   ++i   \n   aac   int   bool   ==   解决   

题目:Space Isaac

传送门:http://codeforces.com/contest/1045/problem/B

分析:

1)我们考虑不能被表示出来的数。

2)设这个数为P,对所有的数x,如果$x \in A$,在那么$(p-x)mod m \in A $;如果$x \in B$,在那么$(p-x)mod m \in B $。否则显然可以表示出这个数。

3)$x$可以分为两段: 小于$P$和大于$P$的情况。当$x<P$时 $P-x<P$;$x>P$时$P-x>P$。

4)考虑枚举分段点$i$,$P=(a[1]+a[i])%m=(a[2]+a[i-1])%m=...$,这就类似个回文串啊。比$P$大的部分同理。

5)然后就是这段经典操作,$b[i]=a[i+1]-a[i];$,再求回文串了。

方法一:

6)回文串可以哈希,顺着、反着各一遍求区间hash值,然后比较是否相等,

7)哈希基于概率,有可能会冲突,简单的做法是双哈希,就是这么暴力,如果还不能解决,那就再来一遍。

 

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL; 
const int maxN=200005;
const ULL HA=41793404541;
int n,m;
int a[maxN],b[maxN];
ULL fac[maxN],pre[maxN],nxt[maxN];
int ansn,ans[maxN];
bool check(int l,int r){
    return pre[r]-pre[l-1]*fac[r-l+1]==nxt[l]-nxt[r+1]*fac[r-l+1];
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    for(int i=1;i< n;++i)b[i]=a[i+1]-a[i];
    fac[0]=1;
    for(int i=1;i<=n;++i)fac[i]=fac[i-1]*HA;
    for(int i=1;i<=n;++i)pre[i]=pre[i-1]*HA+(ULL)b[i];
    for(int i=n-1;i ;--i)nxt[i]=nxt[i+1]*HA+(ULL)b[i];
    for(int i=1;i<=n;++i){
        bool pd=true;
        if(i!=1)pd&=check(1,i-1);
        if(i!=n){
            pd&=(a[1]+a[i]==a[i+1]+a[n]-m);
            if(i!=n-1)pd&=check(i+1,n-1);
        }
        if(pd)ans[++ansn]=(a[1]+a[i])%m;
    }
    printf("%d\n",ansn);
    sort(ans+1,ans+ansn+1);
    for(int i=1;i<=ansn;++i)printf("%d ",ans[i]);
    return 0;
}

 

方法二

8)manachar也是用来解决回文串的有力武器,这里先埋一个坑,捂脸逃。。

题外:

这种题现场过的都是神仙(大雾

 

[CF1045B]Space Isaac

标签:ref   方法   ++i   \n   aac   int   bool   ==   解决   

原文地址:https://www.cnblogs.com/hjj1871984569/p/10390050.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!