BZOJ4377[POI2015] Kurs szybkiego czytania
Description
給定n,a,b,p,其中n,a互質。定義一個長度爲n的01串c[0..n-1],其中c[i]==0當且僅當(ai+b) mod n < p。
給定一個長爲m的小01串,求出小串在大串中出現了幾次。
Input
第一行包含整數n,a,b,p,m
(2<=n<=109,1<=p,a,b,m<n,1<=m<=106) 。n和a互質。第二行一個長度爲m的01串。
Output
一個整數,表示小串在大串中出現了幾次
Sample Input
9 5 6 4 3
101
Sample Output
3
HINT
Solution:
很有意思的一道題。
首先根據這個
然後我們考慮小串的第
設大串匹配的開頭點的
即:
用同樣的方式可以給出
注意:上式取模取正後有可能出現左邊大於右邊的情況,這時其實兩個符號之間是或的關係。
還有一點:大串最後
#include<stdio.h>
#include<iostream>
#include<algorithm>
#define M 1000005
using namespace std;
struct Node{
int L,R;
bool operator <(const Node &a)const{
return L<a.L;
}
}Q[M<<2];
char str[M];
int main(){
int n,a,b,p,m,sz=0;
scanf("%d %d %d %d %d",&n,&a,&b,&p,&m);
scanf("%s",str);
for(int i=0;i<m;i++){
int L,R;
if(str[i]=='0'){//已取反
L=((p-1LL*a*i)%n+n)%n;
R=((n-1LL*a*i-1)%n+n)%n;
}else{
L=((0-1LL*a*i)%n+n)%n;
R=((p-1LL*a*i-1)%n+n)%n;
}
if(L<=R){
Q[++sz]=(Node){L,R};
}else{
Q[++sz]=(Node){0,R};
Q[++sz]=(Node){L,n-1};
}
}
for(int i=n-m+1;i<n;i++)//最後m-1位
Q[++sz]=(Node){(1LL*a*i+b)%n,(1LL*a*i+b)%n};
sort(Q+1,Q+sz+1);
int ed=-1,ans=0;
for(int i=1;i<=sz;i++){
if(ed<Q[i].L)ans+=Q[i].L-ed-1;
if(Q[i].R>ed)ed=Q[i].R;
}
printf("%d\n",ans+(n-1-ed));
return 0;
}