题解 第四题
首先有个审题问题:那个 \(p\) 是最大值,所以 \(p_i \leqslant p_{i-1}+1\) 指的实际上是位置 \(i\) 的数最多比前面的数的最大值大1
我因为看成最多比 \(i-1\) 位置上的数大1浪费了不少时间
- 对计数题求 \(\sum k^2\),其中 \(k\) 为所有组合/方案中某种元素出现次数的处理方法:\[k^2 = 2*\binom{k}{2}+k \]可以先把 \(k^2\) 化为从所有出现位置中选两个的选法数
貌似仍然不好统计,先考虑如何对一种固定的方案求这个选法数
可以脑残 \(n^2\) 枚举元素
推广到对于一个位置 \(i\),从 \(i\) 之后的部分不固定
那 \(i\) 的贡献就是 \(2 \times\)从\(i\)之后的位置选出一个这种元素的方案数\(+2\)
同理推广,每种方案的贡献是 1+在后面再选一个的方案数×2
这部分证明及分析是水过去的,需要问明白
具体到这题……
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 3010
#define ll long long
#define reg register int
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
ll mod, f[N][N], g[N][N], ans[N];
signed main()
{
n=read(); mod=read();
f[0][0]=1;
for (int i=1; i<=n; ++i) g[0][i]=1;
for (int i=1; i<=n; ++i)
for (int j=1; j<=n; ++j) {
f[i][j]=(f[i-1][j]*j%mod+f[i-1][j-1])%mod;
g[i][j]=(g[i-1][j]*j%mod+g[i-1][j+1])%mod;
}
for (int i=1; i<=n; ++i) {
ll sum=0;
for (int x=n; x; --x) {
sum=(sum+f[i-1][x]*(g[n-i][x]+2ll*(n-i)%mod*g[n-i-1][x]%mod)%mod)%mod;
ans[x]=(ans[x]+sum+f[i-1][x-1]*(g[n-i][x]+2ll*(n-i)%mod*g[n-i-1][x]%mod)%mod)%mod;
}
}
for (int i=1; i<=n; ++i) printf("%lld ", ans[i]);
printf("\n");
return 0;
}