传送门
首先考虑对于数字
j
j
j而言,如何计算贡献,假设它有
x
x
x个,那么
x
2
x^2
x2等价于从整个序列中可以重复地选择两个数字
j
j
j的选法。而所有
x
2
x^2
x2之和其实就是从所有可能的序列中重复地选择两个数字
j
j
j的选法之和。
总的来说,两个选法不同,要么两个选法中选择的两个位置存在差异,要么两个选法对应的序列存在差异,这样的话两个选法都会产生一次贡献。
于是对于数字 j j j而言,我们枚举它第一次出现在序列中的位置 i i i,设 p r e [ i ] [ j ] pre[i][j] pre[i][j]表示长度为 i i i的序列,并且 j j j仅仅存在于序列元素最后一个的合法方案数, s u f [ i ] [ j ] suf[i][j] suf[i][j]表示长度为 i i i的序列,并且 j j j作为第一个元素的合法方案数(不考虑 a 0 a_0 a0的限制)。那么对于一个固定的 j , i j,i j,i而言,我们考虑将所有的选法划分为四类:
- 两次都选择位置 i i i,方案数为 p r e [ i ] [ j ] ⋅ s u f [ n − i + 1 ] [ j ] pre[i][j]\cdot suf[n-i+1][j] pre[i][j]⋅suf[n−i+1][j]。
- 一次选择位置 i i i,另一次选择位置 k , ( k > i ) k,(k>i) k,(k>i),方案数为 2 ( n − i ) p r e [ i ] [ j ] ⋅ s u f [ n − i ] [ j ] 2(n-i)pre[i][j]\cdot suf[n-i][j] 2(n−i)pre[i][j]⋅suf[n−i][j](乘二是因为可以第一次选 i i i或第二次选 i i i)
- 两次选择位置 k , ( k > i ) k,(k>i) k,(k>i),方案数为 p r e [ i ] [ j ] ⋅ s u f [ n − i ] [ j ] pre[i][j]\cdot suf[n-i][j] pre[i][j]⋅suf[n−i][j]
- 一次选择位置 k , ( k > i ) k,(k>i) k,(k>i),另一次选择位置 h , ( h > i , h ≠ k ) h,(h>i,h\ne k) h,(h>i,h=k),方案数为 2 C n − i 2 p r e [ i ] [ j ] ⋅ s u f [ n − i − 1 ] [ j ] 2C_{n-i}^2pre[i][j]\cdot suf[n-i-1][j] 2Cn−i2pre[i][j]⋅suf[n−i−1][j]。
将上述四种情况加起来就是对于一个固定 j j j和 i i i而言产生的总贡献,枚举 i i i从 1 ∼ n 1\sim n 1∼n就能求出对于数字 j j j而言的总贡献。
下面考虑 p r e [ i ] [ j ] pre[i][j] pre[i][j]和 s u f [ i ] [ j ] suf[i][j] suf[i][j]如何求解,设 f [ i ] [ j ] f[i][j] f[i][j]表示长度为 i i i的序列最大值为 j j j的合法序列数,那么不难得出 f [ i ] [ j ] = f [ i − 1 ] [ j − 1 ] + f [ i − 1 ] [ j ] ⋅ j f[i][j]=f[i-1][j-1]+f[i-1][j]\cdot j f[i][j]=f[i−1][j−1]+f[i−1][j]⋅j,然后可以发现的是 p r e [ i ] [ j ] = f [ i − 1 ] [ j − 1 ] pre[i][j]=f[i-1][j-1] pre[i][j]=f[i−1][j−1],于是有 p r e [ i ] [ j ] = p r e [ i − 1 ] [ j − 1 ] + p r e [ i − 1 ] [ j ] ⋅ ( j − 1 ) pre[i][j]=pre[i-1][j-1]+pre[i-1][j]\cdot (j-1) pre[i][j]=pre[i−1][j−1]+pre[i−1][j]⋅(j−1)。
再看 s u f [ i ] [ j ] suf[i][j] suf[i][j],考虑第二个位置上的数与 j j j的大小关系:
- 不大于 j j j,此时我们发现第二个位置对后面的位置填什么数字其实没有影响,也就是说我们去掉位置二后,一定存在 s u f [ i − 1 ] [ j ] suf[i-1][j] suf[i−1][j]种方案数,加上位置二,并固定位置二上的数字,仍然存在 s u f [ i − 1 ] [ j ] suf[i-1][j] suf[i−1][j]种方案,不过由于位置二上可以选择 1 ∼ j 1\sim j 1∼j,故总方案为 s u f [ i − 1 ] [ j ] ⋅ j suf[i-1][j]\cdot j suf[i−1][j]⋅j。
- 大于 j j j,只可能是 j + 1 j+1 j+1,此时第一个位置对后面位置填什么数字没有影响,可以去掉,方案数即为 s u f [ i − 1 ] [ j + 1 ] suf[i-1][j+1] suf[i−1][j+1]。
将上面两种情况加起来就能得到: s u f [ i ] [ j ] = s u f [ i − 1 ] [ j + 1 ] + s u f [ i − 1 ] [ j ] ⋅ j suf[i][j]=suf[i-1][j+1]+suf[i-1][j]\cdot j suf[i][j]=suf[i−1][j+1]+suf[i−1][j]⋅j。
int n,pre[maxn][maxn],suf[maxn][maxn];
int main(){
int t=rd(),kase=0;
while(t--){
n=rd(),mod=rd();
pre[1][1]=1;
FOR(i,2,n+1)
FOR(j,2,i+1)pre[i][j]=sum(pre[i-1][j-1],1ll*pre[i-1][j]*(j-1)%mod);
FOR(i,1,n+1)suf[1][i]=1;
FOR(i,2,n+1)
ROF(j,n-1,1)suf[i][j]=sum(suf[i-1][j+1],1ll*suf[i-1][j]*j%mod);
printf("Case #%d:\n",++kase);
FOR(j,1,n+1){
int ans=0;
FOR(i,j,n+1){
add(ans,1ll*pre[i][j]*suf[n-i+1][j]%mod);
add(ans,3ll*pre[i][j]*(n-i)%mod*suf[n-i][j]%mod);
if(i<n)add(ans,1ll*(n-i)*(n-i-1)%mod*pre[i][j]%mod*suf[n-i-1][j]%mod);
}
wr(ans),putchar(' ');
}
puts("");
}
}