1 条题解
-
0
反弹考虑把网格翻转无穷遍就变成直线,而翻转两次相当于平移。
问题转化为给定 ,每次询问 求:
那么我们先转化成求:
$$\sum_{i=0}^L s_{(x+i)\bmod n}\times t_{(y+i)\bmod m}$$发现这个东西看起来很不可做,因为就算 的情况都等价于卷积了。
而 的时候更不好操作,如果任意查询两个区间的对应位置乘法和只能分块 NTT。
那这题能不能规约到查询两个区间的对应位置乘法和呢?
我们考虑现在变量有 ,如果把 移到 就好了,而这一步是查询区间对应位置乘法和。
剩下我们先假设 ,那么 只有 种,把这些 的答案用一遍减法卷积预处理出来为 (具体是先把第二个数组复制若干变,然后就是把第一个数组平移和第二个点乘,翻转就是卷积)。
那么查询可以不断把整段的 跳过去,这一部分对于 每次加上 贡献 ,是一个环上的查询,前缀和一下就可以求出。
剩下还有一段也是区间对应位置乘法。
但是如果真的写了分块 NTT 可能有危险,然而注意到查询比较少,直接 bitset 就好啦!
时间复杂度 。
#include<map> #include<set> #include<ctime> #include<cmath> #include<queue> #include<bitset> #include<cstdio> #include<vector> #include<random> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define ll long long using namespace std; #define I ll #define her1 20081214 #define IV void #define cht 998244353 #define ld long double #define Aestas16 392699 #define ull unsigned long long #define cp(x,y)memcpy(x,y,sizeof y) #define mem(x,val)memset(x,val,sizeof x) #define D(i,j,n)for(register int i=j;i>=n;i--) #define E(i,now)for(register int i=first[now];i;i=e[i].nxt) #define F(i,j,n)for(register int i=j;i<=n;i++) #define DL(i,j,n)for(register i64 i=j;i>=n;i--) #define EL(i,now)for(register i64 i=first[now];i;i=e[i].nxt) #define FL(i,j,n)for(register i64 i=j;i<=n;i++) //#define D(i,j,n)for(int i=j;i>=n;i--) //#define E(i,now)for(int i=first[now];i;i=e[i].nxt) //#define F(i,j,n)for(int i=j;i<=n;i++) //#define DL(i,j,n)for(register ll i=j;i>=n;i--) //#define EL(i,now)for(register ll i=first[now];i;i=e[i].nxt) //#define FL(i,j,n)for(register ll i=j;i<=n;i++) ll read(){ ll ans=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9')ans=ans*10+c-'0',c=getchar(); return ans*f; } #undef ll #include "assert.h" mt19937_64 rnd(her1); #include "functional" using i64 = long long; const int maxn = 2e5+5; bitset<maxn*2>b1,b2,all;bool fg=0;char s[maxn],t[maxn]; i64 n,m,q,X[maxn],Y[maxn],vx[maxn],vy[maxn],L[maxn],Ans[maxn]; i64 calc(i64 x,i64 y){return(b1>>x&b2>>y).count();} vector<i64>s1[maxn],V[maxn];bool vis[maxn]; i64 sum[maxn],idx[maxn],idy[maxn]; #define G 3 i64 rev[(1<<20)+5],f[(1<<20)+5],g[(1<<20)+5]; i64 qpow(i64 n,i64 base=cht-2){ i64 ans=1; while(base){ if(base&1)ans=ans*n%cht; n=n*n%cht;base>>=1; } return ans; } IV NTT(i64*a,i64 limit,bool tp){ i64 sb=__lg(limit); F(i,0,limit-1)rev[i]=(rev[i>>1]>>1|((i&1)<<sb-1)); F(i,0,limit-1)if(i<rev[i])swap(a[i],a[rev[i]]); for(int p=2;p<=limit;p<<=1){ i64 k=(p>>1),wG=qpow(G,(cht-1)/p); for(int l=0,w=1;l<limit;l+=p,w=1) F(i,l,l+k-1){ i64 x=a[i],y=a[i+k]*w%cht; a[i]=(x+y)%cht;a[i+k]=(x-y+cht)%cht; w=w*wG%cht; } } if(tp==1){ i64 inv=qpow(limit); F(i,0,limit-1)a[i]=a[i]*inv%cht; reverse(a+1,a+limit); } } IV solve(i64 r){ if(r==-1){ reverse(t,t+m); } F(i,0,2*maxn-1)all[i]=1; F(i,0,n-1)b1[i]=!(s[i]-'0'); F(i,0,2*m-1)b2[i]=!(t[i%m]-'0'); F(i,0,m-1)vis[i]=0; i64 limit=1; while(limit<=n+2*m)limit<<=1; F(i,0,limit-1)f[i]=g[i]=0; F(i,0,n-1)f[i]=b1[n-1-i]; F(i,0,2*m-1)g[i]=b2[i]; NTT(f,limit,0);NTT(g,limit,0); F(i,0,limit-1)f[i]=f[i]*g[i]%cht; NTT(f,limit,1); F(i,0,m-1)sum[i]=(f[i+n-1]+cht)%cht; i64 cc=0; F(i,0,m-1)if(!vis[i]){ i64 now=i;cc++;V[cc].clear(); while(!vis[now]){ idx[now]=cc;idy[now]=V[cc].size(); V[cc].push_back(sum[now]);vis[now]=1;now=(now+n)%m; } s1[cc]=V[cc]; F(z,1,(i64)s1[cc].size()-1)s1[cc][z]+=s1[cc][z-1]; } F(i,1,q)if(vy[i]==r){ vy[i]=1; if(r==-1)Y[i]=m-1-Y[i]; auto ck=[&](){return s[X[i]]=='0'&&t[Y[i]]=='0';}; if(L[i]<n-X[i]){ Ans[i]-=(all>>2*maxn-L[i]-1&b1>>X[i]&b2>>Y[i]).count(); continue; } Ans[i]-=calc(X[i],Y[i]); Y[i]=(Y[i]+n-X[i])%m;L[i]-=n-X[i];X[i]=0; i64 k=L[i]/n;L[i]%=n; { i64 a=idx[Y[i]],b=idy[Y[i]]; if(k>=s1[a].size()){ Ans[i]-=(k/s1[a].size())*s1[a].back(); k%=s1[a].size(); } if(b+k<s1[a].size()){ if(k)Ans[i]-=(s1[a][b+k-1]-(b?s1[a][b-1]:0)); } else if(k){ Ans[i]-=(s1[a].back()-(b?s1[a][b-1]:0)); if(b+k-1>=V[a].size()){ Ans[i]-=s1[a][b+k-1-(i64)V[a].size()]; } } if(k>=0)Y[i]=(Y[i]+n*k)%m; } Ans[i]-=(all>>2*maxn-L[i]-1&b1&b2>>Y[i]).count(); } } int main(){ // freopen("1.in","r",stdin); // freopen("1.out","w",stdout); n=read();m=read(); scanf("%s%s",s,t);i64 rn=n,rm=m; D(i,rn-2,1)s[n++]=s[i]; D(i,rm-2,1)t[m++]=t[i]; if(n>m)swap(n,m),swap(s,t),fg=1; q=read(); F(i,1,q){ Y[i]=read()-1;X[i]=read()-1;vy[i]=read();vx[i]=read();L[i]=read(); Ans[i]=L[i]+1; if(fg){ swap(X[i],Y[i]);swap(vx[i],vy[i]); } if(vx[i]==-1){ X[i]=(X[i]+vx[i]*L[i]%n+n)%n; Y[i]=(Y[i]+vy[i]*L[i]%m+m)%m; vx[i]=-vx[i];vy[i]=-vy[i]; } } solve(1);solve(-1); F(i,1,q)printf("%lld\n",Ans[i]); return 0; }
- 1
信息
- ID
- 5155
- 时间
- 2000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者