似乎实现方法与题解的都不太一样,我为了方便强行把递推式枚举范围从 [2,n−2] 扩到了 [0,n−1] ,同时在算值的时候给他减了一下,还特意把 f0 设成 0,但反正不管怎样他就是寄了(输出的 f 完全不对),因此在这里求调一下。
NTT 应该是没问题的。
#include<bits/stdc++.h>
#define ri register int
#define ll long long
using namespace std;
const int maxn=1e5+5;
ll f[maxn];
int rev[maxn];
void init(int limit){
for(ri i=1;i<limit;i++){
rev[i]=((rev[i>>1]>>1)|(i&1?limit>>1:0));
}
// for(ri i=0;i<limit;i++)cout<<rev[i]<<' ';cout<<endl;
}
const int mod=998244353;
const int G=3;
ll qpow(ll a,ll b,ll p){
ll ans=1;
while(b){
if(b&1)ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
const int invG=qpow(G,mod-2,mod);
//void NTT(ll f[],int limit,bool tp){
// for(ri i=0;i<limit;i++){
// if(i<rev[i])swap(f[rev[i]],f[i]);
// }
// for(ri len=2;len<=limit;len<<=1){
// ll dwg=qpow(tp?G:invG,(mod-1)/len,mod);
// int pa=len>>1;
// for(ri i=0;i<limit;i+=len){
// ll bf=1;
// for(ri j=i;j<i+pa;j++){
// ll t=bf*f[j+pa]%mod;
// f[j+pa]=(f[j]-t+mod)%mod;
// f[j]=(f[j]+t)%mod;
// bf=bf*dwg%mod;
// }
// }
// }
//}
void NTT(ll f[],int limit,bool tp){
for(ri i=0;i<limit;i++){
if(i<rev[i])swap(f[i],f[rev[i]]);
}
for(ri len=2;len<=limit;len<<=1){
ll dwg=qpow(tp?G:invG,(mod-1)/len,mod);
int pa=len>>1;
for(ri i=0;i<limit;i+=len){
ll bf=1;
for(ri j=i;j<i+pa;j++){
ll t=f[j+pa]*bf%mod;
f[j+pa]=(f[j]-t+mod)%mod;
f[j]=(f[j]+t)%mod;
bf=bf*dwg%mod;
}
}
}
if(!tp){
ll invn=qpow(limit,mod-2,mod);
for(ri i=0;i<limit;i++){
f[i]=(f[i]*invn)%mod;
}
}
}
ll A[maxn],B[maxn];
void test_times(){
int n,m;
cin>>n>>m;
for(ri i=0;i<=n;i++)cin>>A[i];
for(ri i=0;i<=m;i++)cin>>B[i];
n+=m;
int limit=1;
while(limit<=n)limit<<=1;
// cout<<limit<<endl;
init(limit);
NTT(A,limit,1);
NTT(B,limit,1);
for(ri i=0;i<limit;i++)A[i]=A[i]*B[i]%mod;
NTT(A,limit,0);
for(ri i=0;i<=n;i++){
cout<<A[i]<<' ';
}cout<<endl;
exit(0);
}
void solve(int l,int r){
if(l==r-1){
if(l==0)f[l]=0;
else if(l==1)f[l]=2;
else{
f[l]=(f[l]+(l-1)*f[l-1]%mod-(l-2)*f[l-1]%mod*f[1]%mod+mod)%mod;
}
return;
}
int mid=l+r>>1;
solve(l,mid);
int limit=r-l;
// memset(A,0,sizeof(A));
// memset(B,0,sizeof(B));
if(l){
for(ri i=0;i<r-l;i++){
A[i]=f[l+i]*(l+i-1)%mod;
if(i+l>=mid)A[i]=0;
}
for(ri i=0;i<r-l;i++){
B[i]=f[i];
// if(i+l>=mid)B[i]=0;
}
init(r-l);
NTT(A,r-l,1);
NTT(B,r-l,1);
for(ri i=0;i<r-l;i++){
A[i]=A[i]*B[i]%mod;
}
NTT(A,r-l,0);
for(ri i=mid-l;i<r-l;i++){
f[i+l]=(f[i+l]+A[i])%mod;
}
for(ri i=0;i<r-l;i++){
A[i]=f[l+i];
if(i+l>=mid)A[i]=0;
}
for(ri i=0;i<r-l;i++){
B[i]=f[i]*(i-1)%mod;
// if(i+l>=mid)B[i]=0;
}
init(r-l);
NTT(A,r-l,1);
NTT(B,r-l,1);
for(ri i=0;i<r-l;i++){
A[i]=A[i]*B[i]%mod;
}
NTT(A,r-l,0);
for(ri i=mid-l;i<r-l;i++){
f[i+l]=(f[i+l]+A[i])%mod;
}
}
else{
for(ri i=0;i<mid;i++){
A[i]=f[i]*(i-1)%mod;
}
for(ri i=0;i<mid;i++){
B[i]=f[i];
}
for(ri i=mid;i<r;i++){
A[i]=B[i]=0;
}
NTT(A,r-l,1);
NTT(B,r-l,1);
for(ri i=0;i<r-l;i++){
A[i]=A[i]*B[i]%mod;
}
NTT(A,r-l,0);
for(ri i=mid;i<r;i++){
f[i]=(f[i]+A[i])%mod;
}
}
solve(mid,r);
}
int T,n;
int a[maxn];
struct my_stack{
int tot;
int num[maxn];
void push(int x){
num[++tot]=x;
}
void pop(){
--tot;
}
void clear(){
tot=0;
}
int top(){
return num[tot];
}
}st;
vector<int>vec[maxn];
ll calc_ans(){
for(ri i=1;i<=n;i++){
cin>>a[i];
}
for(ri i=1;i<=n;i++){
vec[i].clear();
}
for(ri i=n;i;i--){
if(i-a[i]+1>0)vec[i-a[i]+1].push_back(i);
}
if(a[n]!=n)return 0;
ll ans=1;
for(ri i=1;i<=n;i++){
for(auto x:vec[i]){
st.push(x);
}
if(st.top()!=i){
return 0;
}
else{
st.pop();
}
}
for(ri i=1;i<=n;i++){
for(auto x:vec[i]){
st.push(x-a[x]+1);
}
int cnt=0;
while(st.top()!=i-a[i]+1){
st.pop();
cnt++;
}
ans=ans*f[cnt]%mod;
}
return ans;
}
signed main(){
ios::sync_with_stdio(0);
// test_times();
cin>>T>>n;
int limit=1;
while(limit<=n){
limit<<=1;
}
solve(0,limit);
f[0]=1;
// for(ri i=0;i<limit;i++){
// cout<<f[i]<<' ';
// }cout<<endl;
while(T--){
cout<<calc_ans()<<endl;
}
return 0;
}