解析
不难发现有效的状态只有 S=C113=165S=C_{11}^3=165S=C113=165 种。
同时,能支持 n=1018n=10^{18}n=1018 的算法也不剩啥了,要么拉插,要么矩乘。
本题当然就是矩乘了,转移矩阵也较为显然。
然而,直接做的话复杂度是 O(TS3logn)O(TS^3\log n)O(TS3logn) 的,只有 60pts。
然后就有一个很简单但效果非常显著的优化:每次不再像正常矩阵快速幂一样求出转移矩阵的 nnn 次方,而是预处理出所有 2i2^i2i 的转移矩阵,然后把答案行矩阵和需要的转移矩阵分别乘即可,复杂度 O(TS2logn)O(TS^2\log n)O(TS2logn)。
不要僵化思维!
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
using namespace std;const int N=2050;
const double eps=1e-10;
const int mod=998244353;
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}inline ll ksm(ll x,ll k){ll res(1);while(k){if(k&1) res=res*x%mod;x=x*x%mod;k>>=1;}return res;
}int n,m,k;
struct matrix{ll a[205][205];int x,y;matrix(int X=0,int Y=0):x(X),y(Y){memset(a,0,sizeof(a));}
};
matrix operator * (const matrix &u,const matrix &v){matrix res(u.x,v.y);for(int k=1;k<=u.y;k++){for(int i=1;i<=u.x;i++){ll tmp=u.a[i][k];for(int j=1;j<=v.y;j++){(res.a[i][j]+=tmp*v.a[k][j])%=mod;}}}return res;
}int id[10][10][10],tot;
struct state{int x,y,z;
};
matrix mi[100];matrix calc(ll k){matrix res(tot+1,tot+1);for(int i=1;i<=tot+1;i++) res.a[i][i]=1;int cnt(0);while(k){if(k&1) res=res*mi[cnt];cnt++;k>>=1;}return res;
}signed main(){
#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);
#endifint T=read();m=read();k=read();for(int i=0;i<=k;i++){for(int j=0;i+j<=k;j++){for(int p=0;i+j+p<=k;p++){id[i][j][p]=++tot;//printf("(%d %d %d) id=%d\n",i,j,p)if(m<=2) break;}if(m<=1) break;}}matrix trans(tot+1,tot+1);for(int a=0;a<=k;a++){for(int b=0;a+b<=k;b++){for(int c=0;c<=k;c++){int add2=(m==2&&min(1,k-a-b-c)),add3=(m==3&&min(1,k-a-b-c)),now=id[a][b][c];if(!now) continue;ll p=ksm(a+b+c+1,mod-2);trans.a[tot+1][now]=trans.a[now][now]=p;if(a) trans.a[ id[a-1][b][c] ][now]=p*a%mod;if(b) trans.a[ id[a+1][b-1+add2][c+add3] ][now]=p*b%mod;if(c) trans.a[ id[a][b+1+add2][c-1+add3] ][now]=p*c%mod; }}}trans.a[tot+1][tot+1]=1;int s;if(m==1) s=id[1][0][0];if(m==2) s=id[0][1][0];if(m==3) s=id[0][0][1];mi[0]=trans;for(int i=1;i<=60;i++) mi[i]=mi[i-1]*mi[i-1];matrix ori(1,tot+1);ori.a[1][tot+1]=1;while(T--){ll n=read();int cnt(0);matrix res=ori;while(n){if(n&1) res=res*mi[cnt];++cnt;n>>=1;}printf("%lld\n",res.a[1][s]);}return 0;
}