[loj6738]王的象棋世界
记$A=\left(\begin{matrix}1&1&\\1&1&1\\&1&1&1\\&&\ddots&\ddots&\ddots\\&&&1&1&1\\&&&&1&1\\\end{matrix}\right)$,问题即求$ans=A^{R-1}_{x,y}$
考虑其特征多项式,即$f_{C}(t)=|tI-A|$(其中$I$为单位矩阵)
对最后一行所选的元素分类讨论,可得递推式$f_{C}(t)=(t-1)f_{C-1}(t)-f_{C-2}(t)$
代入单位根并通过矩阵乘法(求出点值)+IDFT即可求出$f_{C}(t)$,时间复杂度为$o(C\log C)$
分治+多项式求出$F(t)=t^{R-1}\ mod\ f_{C}(t)$,时间复杂度为$o(C\log R\log C)$
根据特征多项式的性质,可得$ans=F(A)=\sum_{i=0}^{C-1}[t^{i}]F(t)\cdot A^{i}_{x,y}$
由于$i<C$,两个边界不会同时越界,翻折容斥可得
$$
A^{i}_{x,y}=[t^{x-y}]g_{i}(t)-[t^{x+y}]g_{i}(t)-[t^{x+y-2(C+1)}]g_{i}(t)
$$
(其中$g_{i}(t)=(t+1+\frac{1}{t})^{i}$,即在无边界时走$i$步)
将$g_{i}(t)$累加,同样分治+多项式求出$G(t)=\sum_{i=0}^{C-1}[t^{i}]F(t)\cdot g_{i}(t)$,时间复杂度为$o(C\log^{2}C)$
在此基础上,有$ans=[t^{x-y}]G(t)-[t^{x+y}]G(t)-[t^{x+y-2(C+1)}]G(t)]$,即可$o(1)$询问
总复杂度为$o(C\log R\log C+C\log^{2}C+Q)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define L 18 4 #define N (1<<L) 5 #define mod 998244353 6 #define ll long long 7 #define vi vector<int> 8 int n,inv,R,C,Q,x,y,rev[N],w[2][L][N]; 9 vi a,a0,b,c,g[L],f[L]; 10 struct mat{ 11 int a[2][2]; 12 mat operator * (const mat &b)const{ 13 mat ans=mat{0,0,0,0}; 14 for(int i=0;i<2;i++) 15 for(int j=0;j<2;j++) 16 for(int k=0;k<2;k++)ans.a[i][k]=(ans.a[i][k]+(ll)a[i][j]*b.a[j][k])%mod; 17 return ans; 18 } 19 }A; 20 int qpow(int n,int m){ 21 int s=n,ans=1; 22 while (m){ 23 if (m&1)ans=(ll)ans*s%mod; 24 s=(ll)s*s%mod,m>>=1; 25 } 26 return ans; 27 } 28 mat qpow(mat n,int m){ 29 mat s=n,ans=mat{1,0,0,1}; 30 while (m){ 31 if (m&1)ans=ans*s; 32 s=s*s,m>>=1; 33 } 34 return ans; 35 } 36 void init_lg(int m){ 37 n=inv=1; 38 while (n<m)n<<=1,inv=(ll)inv*(mod+1>>1)%mod; 39 for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)+(i&1)*(n>>1); 40 } 41 void ntt(vi &a,int p=0){ 42 for(int i=0;i<n;i++) 43 if (i<rev[i])swap(a[i],a[rev[i]]); 44 for(int i=2,t=0;i<=n;i<<=1,t++) 45 for(int j=0;j<n;j+=i) 46 for(int k=0;k<(i>>1);k++){ 47 int x=a[j+k],y=(ll)w[p][t][k]*a[j+k+(i>>1)]%mod; 48 a[j+k]=(x+y)%mod,a[j+k+(i>>1)]=(x-y+mod)%mod; 49 } 50 if (p){ 51 for(int i=0;i<n;i++)a[i]=(ll)a[i]*inv%mod; 52 } 53 } 54 vi get_inv(vi a,int m){ 55 vi ans; 56 if (m==1){ 57 ans.push_back(qpow(a[0],mod-2)); 58 return ans; 59 } 60 vi s=get_inv(a,(m+1>>1)); 61 init_lg(m<<1),ans=s,a.resize(n),s.resize(n),ans.resize(m); 62 for(int i=m;i<n;i++)a[i]=0; 63 ntt(a),ntt(s);for(int i=0;i<n;i++)s[i]=(ll)a[i]*s[i]%mod*s[i]%mod;ntt(s,1); 64 for(int i=0;i<m;i++)ans[i]=((ans[i]<<1)%mod-s[i]+mod)%mod; 65 return ans; 66 } 67 void calc(int d,int l,int r){ 68 if (l==r){ 69 g[d]=vi{1,1,1},f[d]=vi{b[l]}; 70 return; 71 } 72 int mid=(l+r>>1); 73 calc(d+1,l,mid),g[d]=g[d+1],f[d]=f[d+1],calc(d+1,mid+1,r); 74 init_lg((r-l<<1)+3),g[d].resize(n),g[d+1].resize(n),f[d].resize(n),f[d+1].resize(n); 75 for(int i=n-1;i>=r-mid;i--)f[d][i]=f[d][i-(r-mid)]; 76 for(int i=0;i<r-mid;i++)f[d][i]=0; 77 ntt(g[d]),ntt(g[d+1]),ntt(f[d]),ntt(f[d+1]); 78 for(int i=0;i<n;i++){ 79 f[d][i]=(f[d][i]+(ll)g[d][i]*f[d+1][i])%mod; 80 g[d][i]=(ll)g[d][i]*g[d+1][i]%mod; 81 } 82 ntt(g[d],1),ntt(f[d],1),g[d].resize((r-l<<1)+3),f[d].resize((r-l<<1)+1); 83 } 84 int get(int k){ 85 if (abs(k)>=C)return 0; 86 return f[0][k+C-1]; 87 } 88 int main(){ 89 for(int i=0;i<L;i++){ 90 w[0][i][0]=w[1][i][0]=1; 91 w[0][i][1]=qpow(3,(mod-1>>i+1)); 92 w[1][i][1]=qpow(w[0][i][1],mod-2); 93 for(int j=2;j<(1<<i);j++){ 94 w[0][i][j]=(ll)w[0][i][j-1]*w[0][i][1]%mod; 95 w[1][i][j]=(ll)w[1][i][j-1]*w[1][i][1]%mod; 96 } 97 } 98 scanf("%d%d%d",&R,&C,&Q); 99 init_lg(C+1),a.resize(n); 100 for(int i=0;i<n;i++){ 101 A=mat{0,mod-1,1,qpow(3,(mod-1)/n*i)-1}; 102 a[i]=qpow(A,C).a[1][1]; 103 } 104 ntt(a,1),reverse(a.begin(),a.begin()+C+1),a0=get_inv(a,C+1); 105 init_lg(C<<1),a.resize(n),a0.resize(n),b.resize(n),ntt(a),ntt(a0),b[0]=1; 106 for(int i=29;i>=0;i--){ 107 ntt(b);for(int j=0;j<n;j++)b[j]=(ll)b[j]*b[j]%mod;ntt(b,1); 108 if ((R-1>>i)&1){ 109 for(int j=(C<<1)-1;j;j--)b[j]=b[j-1];b[0]=0; 110 } 111 reverse(b.begin(),b.begin()+(C<<1)),c=b; 112 for(int j=C;j<n;j++)c[j]=0; 113 ntt(c);for(int j=0;j<n;j++)c[j]=(ll)c[j]*a0[j]%mod;ntt(c,1); 114 for(int j=C;j<n;j++)c[j]=0; 115 ntt(c);for(int j=0;j<n;j++)c[j]=(ll)c[j]*a[j]%mod;ntt(c,1); 116 for(int j=0;j<(C<<1);j++)b[j]=(b[j]-c[j]+mod)%mod; 117 for(int j=0;j<C;j++)b[j]=b[j+C]; 118 for(int j=C;j<(C<<1);j++)b[j]=0; 119 reverse(b.begin(),b.begin()+C); 120 } 121 calc(0,0,C-1); 122 while (Q--){ 123 scanf("%d%d",&x,&y); 124 printf("%d\n",((get(x-y)-get(x+y)+mod)%mod-get(x+y-(C+1<<1))+mod)%mod); 125 } 126 return 0; 127 }