1. 程式人生 > >[數論] 2017 計蒜之道 初賽 第一場 阿里天池的新任務

[數論] 2017 計蒜之道 初賽 第一場 阿里天池的新任務

我們令子串Ss,t對應的ws為這個子串的b
因為互質 所以b是互不相同的 轉為求有幾個b滿足條件
然後每一位看作一個限制 把所有限制離散化取交即可 注意處理奇偶性
還有一個細節 snm+1 我們還要倒著把最後m1b中合法的減掉

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#define pb push_back
using namespace std;
typedef long long
ll; const int N=1000005; int n,a,b,L,R; int m; char t[N]; int tot; int l[N<<2],r[N<<2]; bool e[N<<2]; inline void add(ll _L,ll _R,ll ax,int t){ if (_L>_R) return; ll L=(_L+n-ax%n)%n,R=(_R+n-ax%n)%n; if (L<=R){ l[++tot]=L,r[tot]=R; e[tot]=t^((L&1)^(_L&1)); }else
{ l[++tot]=0,r[tot]=R; e[tot]=t^((R&1)^(_R&1)); l[++tot]=L,r[tot]=n-1; e[tot]=t^((L&1)^(_L&1)); } } int sx[N<<3],icnt; int idx[N<<3],cnt; int T[N<<3][2]; inline bool cmp(int x,int y){ return (x>0?l[x]:r[-x])<(y>0?l[y]:r[-y]); } inline int
calc(int l,int r,int t){ if (t==1){ if (~l&1) l++; if (r&1) r++; return (r-l+1)>>1; }else{ if (l&1) l++; if (~r&1) r++; return (r-l+1)>>1; } } int main(){ freopen("t.in","r",stdin); freopen("t.out","w",stdout); scanf("%d%d%d%d%d",&n,&a,&b,&L,&R); scanf("%s",t+1); m=strlen(t+1); for (int i=1;i<=m;i++) if (t[i]=='A'){ add(L,R,(ll)a*(i-1)%n,0); }else if (t[i]=='T'){ add(L,R,(ll)a*(i-1)%n,1); } else if (t[i]=='G'){ add(0,L-1,(ll)a*(i-1)%n,0); add(R+1,n-1,(ll)a*(i-1)%n,0); }else if (t[i]=='C'){ add(0,L-1,(ll)a*(i-1)%n,1); add(R+1,n-1,(ll)a*(i-1)%n,1); } sx[++icnt]=0; sx[++icnt]=n; for (int i=1;i<=tot;i++){ sx[++icnt]=l[i],sx[++icnt]=r[i]+1; } sort(sx+1,sx+icnt+1); icnt=unique(sx+1,sx+icnt+1)-sx-1; for (int i=1;i<=tot;i++){ l[i]=lower_bound(sx+1,sx+icnt+1,l[i])-sx; r[i]=lower_bound(sx+1,sx+icnt+1,r[i]+1)-sx; idx[++cnt]=i,idx[++cnt]=-i; } sort(idx+1,idx+cnt+1,cmp); ll t[2]={0,0}; int pnt=1; ll ans=0; for (int i=1;i<icnt;i++){ while (pnt<=cnt && (idx[pnt]>0?l[idx[pnt]]:r[-idx[pnt]])==i) if (idx[pnt]>0) t[e[idx[pnt]]]++,pnt++; else t[e[-idx[pnt]]]--,pnt++; T[i][0]=t[0]; T[i][1]=t[1]; if (t[0]==m) ans+=calc(sx[i],sx[i+1]-1,0); if (t[1]==m) ans+=calc(sx[i],sx[i+1]-1,1); } for (int i=1;i<m;i++){ b=(b+n-a)%n; int it=upper_bound(sx+1,sx+icnt+1,b)-sx-1; if (T[it][b&1]==m) ans--; } printf("%lld\n",ans); return 0; }