[题解] P3589 [POI2015] KUR
Change log
- 2023.9.22 修改少量 LaTeX 的使用。
\color{red}博客内食用效果更佳(点我)
复杂度:O(n\log n)
完整思路
纯纯的思维好题。考虑对所求答案的转化。
设小串为
我们将题意转化为求合法
当
当
接下来以
于是我们得到了
考虑到值域很大,所以把每个
代码实现需要注意的地方:
- 在差分过程中注意
l>r 的情况,这就是上文所说的两个区间的解集。 - 求
l,r 的时候进行减法可能出现负数,要加上n 后再对其取模。
参考代码:
#include<bits/stdc++.h>
#define LL long long
#define UN unsigned
using namespace std;
//--------------------//
const int N=1e6+5,N2=2e6+5;
int n,a,b,p,m,s[N];
char str[N];
int tcnt,sum[N2],de[N];
LL tp[N2];
LL l[N],r[N];
//--------------------//
int main()
{
scanf("%d%d%d%d%d%s",&n,&a,&b,&p,&m,str+1);
for(int i=1;i<=m;i++)
{
s[i]=str[i]-'0';
if(s[i])//求 l,r
{
l[i]=((p-1LL*a*(i-1)%n-b)%n+n)%n;
r[i]=((n-1LL*a*(i-1)%n-b)%n+n)%n;
}
else
{
l[i]=((0-1LL*a*(i-1)%n-b)%n+n)%n;
r[i]=((p-1LL*a*(i-1)%n-b)%n+n)%n;
}
tp[++tcnt]=l[i],tp[++tcnt]=r[i];
}
tp[++tcnt]=0,tp[++tcnt]=n;
sort(tp+1,tp+tcnt+1);
tcnt=unique(tp+1,tp+tcnt+1)-tp-1;
for(int i=1;i<=m;i++)
{
l[i]=lower_bound(tp+1,tp+tcnt+1,l[i])-tp;
r[i]=lower_bound(tp+1,tp+tcnt+1,r[i])-tp;
sum[l[i]]++,sum[r[i]]--,sum[1]+=(l[i]>r[i]);//离散后差分
}
int ans=0,cnt=0;
for(int i=2;i<=tcnt;i++)
sum[i]+=sum[i-1];
for(int i=n-m+1;i<n;i++)
de[++cnt]=1LL*a*i%n;//预处理不合法解
sort(de+1,de+cnt+1);
for(int now=0,las,i=1;i<tcnt;i++)
{
las=now;
while(now+1<=cnt&&de[now+1]<tp[i+1])//双指针扫描在符合条件 aq 中的不合法区间
now++;
if(sum[i]==m)
ans+=tp[i+1]-tp[i]-(now-las);
}
printf("%lld",ans);
return 0;
}