題目
思路簡單代碼毒瘤的經典簡單OI題,真的只需要會倍增
題解主要就是一句話:一個意義下的多項式的平方就是每一項的指數,那麼可以考慮使用遞歸形式的快速冪來利用可快速平方和乘一個原多項式的性質,又因爲需求串長度,所以我們可以考慮存長度爲需求串長的所有串的個數,並在倍增時簡單轉移所有串的個數,並且每次刪除最前面的若干字符來求在區間的串的個數即可得到的個數,最後只需要考慮一下邊界情況,存最前面的個字符即可。
。。。。。。
簡單轉移預處理即可。
邊界處理__大法好。
限制刪除求出倍增的每個時刻最少需要留多少位,即可保證每次都只刪除個字符。
#include<bits/stdc++.h>
#define LL long long
#define LLL __int128
using namespace std;
#define maxn 1<<19|1
LL S,SS,t,st,qy,tr[4][maxn];
int T,n,k;
LL m,L,R,F[maxn],G[maxn],*f=F,*g=G;
LL Query(LL r){
if(r<0) return 0;
static LL q[100],up[100];LL m=::m,Len=n,del;
q[q[0]=1]=r,up[1]=m&1,m>>=1;
for(;m>1;m>>=1) q[0]++,q[q[0]]=max((q[q[0]-1]+1)>>1,t),up[q[0]]=m&1;
for(int i=0;i<=n;i++) f[st<<(t-i)&S]++;
LLL bef=st<<(t+1),beg;
if(::m>1) for(;q[0];q[0]--){
swap(f,g);
LL tg=up[q[0]],*t1=tr[0+tg*2],*t2=tr[1+tg*2];
for(int i=0;i<(1<<(t+1));i++) if(g[i]) f[t1[i]]+=g[i],f[t2[i]]+=g[i],g[i]=0;
Len=(Len<<1)+(tg*t),del=max(0ll,Len-q[q[0]]);
beg=0;
for(int i=0;i<=(t<<1|1);i++) beg|=(bef>>i&1)<<(i<<1);
if(!tg){
for(int i=0;i<del;i++) f[(beg>>(3*t+2-i))&S]--;
bef=(beg>>(2*t+1-del)&SS);
}
else{
bef=0; for(int i=0;i<=t;i++) if(st>>i&1) bef^=beg<<i;
for(int i=0;i<t;i++) f[bef>>(4*t+2-i)&S]++;
for(int i=0;i<del;i++) f[bef>>(4*t+2-i)&S]--;
bef=(bef>>(3*t+1-del)&SS);
}
f[0]--,Len-=del;
}
LL ret = 0;
for(int i=0;i<(1<<(t-k));i++) ret += f[i|qy];
memset(F,0,sizeof F),memset(G,0,sizeof G);
return ret;
}
int main(){
for(scanf("%d",&T);T--;){
scanf("%d%lld%d%lld%lld",&n,&m,&k,&L,&R);t=max(n,--k);
char ch;for(;!isdigit(ch=getchar()););
st = (ch-'0')<<t;
for(int i=1;i<=n;i++)
st|=(getchar()-'0')<<(t-i);
for(;!isdigit(ch=getchar()););
qy = (ch-'0')<<t;
for(int i=1;i<=k;i++)
qy|=(getchar()-'0')<<(t-i);
S=(1<<(t+1))-1;
SS=(1ll<<(2*t+2))-1;
for(LL i=0;i<(1<<(t+1));i++){
LL v=0,e=0;
for(int j=0;j<=t;j++) v|=(i>>j&1)<<(j<<1);
tr[0][i] = v>>t , tr[1][i]=v>>(t-1)&S;
for(int j=0;j<=t;j++) if(st>>j&1) e^=v<<j;
tr[2][i] = e>>t&S, tr[3][i]=e>>(t-1)&S;
}
printf("%lld\n",R-L+1<k?0:Query(n*m+1-L)-Query(n*m+1-R-1+k));
}
}