题目大意
一个长为n的哈希表,每次在ai处加一个元素,其可以往左或往右找位置,设x为最终位置,则贡献为|ai-x|
对所有的不走出边界的a和所有的方向集合b求和,模p
n<=500,p是质数
题解
ll:也是简单题
于是顺便把标爆成了nlogn
一开始以为可以走出边界,后来发现看错了
所以直接设一段的方案f与答案g,枚举最后一个的位置简单转移
之后设h[i,j,0/1]随便合并即可,注意不要瞎写否则会T
nlog?n:https://blog.csdn.net/qq_43649416/article/details/109788530
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define add(a,b) a=((a)+(b))%mod
#define min(a,b) (a<b?a:b)
#define ll long long
//#define file
using namespace std;
ll jc[501],Jc[501],f[501],g[501],h[501][501][2],C[501][501],s,ans,F;
int n,m,mod,Mod,i,j,k,l;
ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
int main()
{
#ifdef file
freopen("CF1439D.in","r",stdin);
#endif
scanf("%d%d%d",&n,&m,&mod),Mod=mod-2;
jc[0]=1;
fo(i,1,n) jc[i]=jc[i-1]*i%mod;
Jc[n]=qpower(jc[n],Mod);
fd(i,n-1,0) Jc[i]=Jc[i+1]*(i+1)%mod;
C[0][0]=1;
fo(i,1,n)
{
C[i][0]=C[i][i]=1;
fo(j,1,i-1) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
f[0]=1;g[0]=0;
fo(i,1,m)
{
fo(j,1,i)
{
s=(j*(j-1)/2+(i-j+1)*(i-j)/2)%mod;
add(f[i],f[j-1]*f[i-j]%mod*(i+1)%mod*C[i-1][j-1]);
add(g[i],((g[j-1]*f[i-j]+f[j-1]*g[i-j])%mod*(i+1)+f[j-1]*f[i-j]%mod*s)%mod*C[i-1][j-1]);
}
}
h[0][0][0]=1;
fo(i,0,min(m,n-m+1)-1)
{
fo(j,0,m-1)
{
fo(k,1,m-j)
{
F=f[k]*C[j+k][j]%mod;
add(h[i+1][j+k][0],h[i][j][0]*F);
add(h[i+1][j+k][1],h[i][j][1]*F);
add(h[i+1][j+k][1],h[i][j][0]*g[k]%mod*C[j+k][j]);
}
}
}
fo(i,1,min(m,n-m+1)) add(ans,h[i][m][1]*C[n-m+1][i]);
printf("%lld
",(ans+mod)%mod);
fclose(stdin);
fclose(stdout);
return 0;
}