题目: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 ",ansn); sort(ans+1,ans+ansn+1); for(int i=1;i<=ansn;++i)printf("%d ",ans[i]); return 0; }
方法二
8)manachar也是用来解决回文串的有力武器,这里先埋一个坑,捂脸逃。。
坑
题外:
这种题现场过的都是神仙(大雾