[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 }
View Code

 

posted @ 2022-03-22 11:00  PYWBKTDA  阅读(136)  评论(0编辑  收藏  举报