【UER #4】量子态的棋盘
好像是轮廓线DP。
#include<bits/stdc++.h> #define ull unsigned long long #define LL long long #define mo 998244353 #define B 80 using namespace std; //const int _P=1000007; //const int _N=1000005; //struct HashMap{ // int head[_P],inum,clk; // int tag[_P]; // ull h[_N]; int c[_N],g[_N],next[_N]; // void _new(){ // ++clk; inum=0; // } // int Head(int x){ // return tag[x]!=clk?(tag[x]=clk,head[x]=0):head[x]; // } // int &get(ull _h,int _c){ // int hs=(_h*233+_c)%_P; // for (int p=Head(hs);p;p=next[p]) // if (h[p]==_h && c[p]==_c) // return g[p]; // h[++inum]=_h; c[inum]=_c; g[inum]=0; next[inum]=head[hs]; head[hs]=inum; // return g[inum]; // } //}f[2]; struct Ha{ #define HaN 1000007 #define HaM 1000007 int head[HaN],net[HaM],fall[HaM],tag[HaN],tot,tim, c[HaM],g[HaM]; ull h[HaM]; void _new() {++tim; tot=0;} int push(int x) { return (tag[x]^tim)?(tag[x]=tim,head[x]=0):head[x]; } int &get(ull _h,int _c) { static int hs; hs=(_h*233+_c)%HaN; for (int i=push(hs);i;i=net[i]) if (h[i]==_h&&c[i]==_c) return g[i]; h[++tot]=_h,c[tot]=_c; g[tot]=0; net[tot]=head[hs]; head[hs]=tot; return g[tot]; } }f[2]; int n,m,g,p,c,nc; char ha[107],pa[107]; LL K,ff[107][107],sum[107*107],l,r,ans; ull se[107],h,tt,nh; signed main () { // freopen("c.in","r",stdin); scanf("%d%d%lld",&n,&m,&K); scanf("%s",ha+1); scanf("%s",pa+1); ff[1][1]=K; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) ff[i+1][j]+=ff[i][j]>>1,ff[i][j+1]+=ff[i][j]>>1,ff[i][j]&=1; for (int i=1;i<=n;i++) ans+=(ha[i]=='1')*ff[i][m+1],ff[i][m+1]=0; for (int i=1;i<=m;i++) ans+=(pa[i]=='1')*ff[n+1][i],ff[n+1][i]=0; se[0]=1; for (int i=1;i<=m;i++) se[i]=se[i-1]*B; int t=0; f[t]._new(); ull tmp=0; for (int i=m;i;i--) tmp=tmp*B+ff[1][i]; f[t].get(tmp,0)=1; for (int i=1;i<=n*m;i++,t^=1){ int x=(i-1)/m+1,y=(i-1)%m+1; f[t^1]._new(); for (int p=1;p<=f[t].tot;p++){ h=f[t].h[p]; c=f[t].c[p],g=f[t].g[p]; tt=h%80; nh=h/80+se[m-1]*ff[x+1][y]; nc=c; if (y<m) nh+=(tt+1)/2; else nc+=((tt+1)/2)*(ha[x]=='1'); if (x<n) nh+=se[m-1]*(tt/2); else nc+=(tt/2)*(pa[y]=='1'); // cerr<<nh<<' '<<nc<<endl; (f[t^1].get(nh,nc)+=g)%=mo; nh=h/80+se[m-1]*ff[x+1][y]; nc=c; if (y<m) nh+=tt/2; else nc+=(tt/2)*(ha[x]=='1'); if (x<n) nh+=se[m-1]*((tt+1)/2); else nc+=((tt+1)/2)*(pa[y]=='1'); // cerr<<nh<<' '<<nc<<endl; (f[t^1].get(nh,nc)+=g)%=mo; } } for (int q=1;q<=f[t].tot;q++) (sum[f[t].c[q]]+=f[t].g[q])%=mo; for (int i=1;i<=n*m;i++) (sum[i]+=sum[i-1])%=mo; scanf("%d",&p); while (p--) { scanf("%lld%lld",&l,&r); l=max(l,ans); r=min(r,ans+n*m); if (l>r){printf("0\n"); continue;} if (l==ans) printf("%d\n",sum[r-ans]); else printf("%d\n",(sum[r-ans]+mo-sum[l-ans-1])%mo); } return 0; }