BZOJ4377[POI2015] Kurs szybkiego czytania
2016-10-18 10:58
253 查看
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
![](http://www.lydsy.com/JudgeOnline/upload/201601/tabelka.png)
Solution:
很有意思的一道题。
首先根据这个n与a互质,可以得出(ai+b)modn是[0,n)的一个全排列。
然后我们考虑小串的第i位与大串的某一位匹配了,设此点在大串中的值为x=(ai+b)%n。由于它满足于p的大小关系,可以列出一条式子:(假设小串第i位为0)
0≤x<p
设大串匹配的开头点的x值为x0,可以得到:(小串下标从1开始)
−a∗(i−1)%n≤(x−a∗(i−1))%n<(p−a∗(i−1))%n
即:
−a∗(i−1)%n≤x0<(p−a∗(i−1))%n
用同样的方式可以给出m条限制的式子,只需要求出这些的交集就可以了。但这并不好做,可以将所有的区间取个反,然后按左端点排序求补集大小,就可以了。
注意:上式取模取正后有可能出现左边大于右边的情况,这时其实两个符号之间是或的关系。
还有一点:大串最后m−1个点也是不能作为x0的位置,要处理掉。
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
![](http://www.lydsy.com/JudgeOnline/upload/201601/tabelka.png)
Solution:
很有意思的一道题。
首先根据这个n与a互质,可以得出(ai+b)modn是[0,n)的一个全排列。
然后我们考虑小串的第i位与大串的某一位匹配了,设此点在大串中的值为x=(ai+b)%n。由于它满足于p的大小关系,可以列出一条式子:(假设小串第i位为0)
0≤x<p
设大串匹配的开头点的x值为x0,可以得到:(小串下标从1开始)
−a∗(i−1)%n≤(x−a∗(i−1))%n<(p−a∗(i−1))%n
即:
−a∗(i−1)%n≤x0<(p−a∗(i−1))%n
用同样的方式可以给出m条限制的式子,只需要求出这些的交集就可以了。但这并不好做,可以将所有的区间取个反,然后按左端点排序求补集大小,就可以了。
注意:上式取模取正后有可能出现左边大于右边的情况,这时其实两个符号之间是或的关系。
还有一点:大串最后m−1个点也是不能作为x0的位置,要处理掉。
#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; }
相关文章推荐
- BZOJ4377 : [POI2015]Kurs szybkiego czytania
- [思路题 乱搞] BZOJ 4377 [POI2015]Kurs szybkiego czytania
- 4377: [POI2015]Kurs szybkiego czytania
- BZOJ4377 POI2015 Kurs szybkiego czytania
- BZOJ4377: [POI2015]Kurs szybkiego czytania
- BZOJ4377: [POI2015]Kurs szybkiego czytania
- BZOJ4382 : [POI2015]Podział naszyjnika
- bzoj 4377 Kurs szybkiego czytania 数学思维题
- 【bzoj3747】【POI2015】【Kinoman】【线段树】
- bzoj 4384: [POI2015]Trzy wieże 树状数组
- 【BZOJ4379】[POI2015]Modernizacja autostrady 树形DP
- [BZOJ4381][POI2015]Odwiedziny (树链刨分/倍增)
- BZOJ 3749 [POI2015]Łasuchy
- 【BZOJ3747】[POI2015]Kinoman【线段树】
- BZOJ4383 : [POI2015]Pustynia
- 【BZOJ3750】[POI2015]Pieczęć【暴力】
- [BZOJ3747][POI2015]Kinoman(线段树)
- [BZOJ]3747: [POI2015]Kinoman 线段树
- BZOJ4385: [POI2015]Wilcze doły
- bzoj 3747: [POI2015]Kinoman(线段树)