P7986
P7986 [USACO21DEC] HILO P
一种纯推式子的方法,不需要期望和 dp。
下面记原题的
修改了一些排版问题()
O(n^5) solution
考虑计算每一对 HILO 对答案造成的贡献,发现一对 HILO 必定能由排列中的一对有序对
于是直接枚举
- 对于所有
1\le l<j,p_l >x 或者p_l<y ,记作条件 1。
这样才会使
但这是不够的。考虑排列 1 5 2 3 4 6,在
按照
- 若存在,对于每一个
x,y,i,j,z ,答案即为A_{n-x+z-1}^{j-3}\times (n-j)!\times (i-1) ,表示在能选的所有数(即[x+1,n],[1,z-1] 之间的所有数)之中选出一些数放在前j-3 个位置上(前j 个位置去掉已经钦定好了的x,y,z )并随意排列,j 之后的数任意排列,z 可以放置在[1,i-1] 的任意位置的方案数,其中A 是排列数。 - 若不存在,对于每一个
x,y,i,j ,答案即为A_{n-x}^{j-2}\times(n-j)! ,意义和存在的情况类似。
枚举
通过第一个子任务。
void On5sol(){
rep(i,2,n)rep(j,i+1,n)rep(x,k+1,n)rep(y,1,k)rep(z,1,y-1){
ans=(ans+A(n-x+z-1,j-3)*fac[n-j]%mod*(i-1)%mod)%mod;
}
rep(i,1,n)rep(j,i+1,n)rep(x,k+1,n)rep(y,1,k){
ans=(ans+A(n-x,j-2)*fac[n-j]%mod)%mod;
}
}
O(n^4) solution
优化上述式子,发现答案式子与
注意在不存在
通过第一个子任务。
void On4sol(){
rep(i,2,n)rep(j,i+1,n)rep(x,k+1,n)rep(z,1,k){
ans=(ans+A(n-x+z-1,j-3)*fac[n-j]%mod*(i-1)%mod*(k-z)%mod)%mod;
}
rep(i,1,n)rep(j,i+1,n)rep(x,k+1,n){
ans=(ans+A(n-x,j-2)*fac[n-j]%mod*k%mod)%mod;
}
}
O(n^3) solution
继续优化上述式子,以存在
不存在
预处理是
虽然名字是 dp 但这个做法真的与 dp 无关
通过第一,二个子任务。
void On3sol(){
rep(j,3,n)rep(x,k+1,n)rep(z,1,k)dp[j]=(dp[j]+A(n-x+z-1,j-3)*fac[n-j]%mod*(k-z)%mod)%mod;
rep(i,2,n)rep(j,i+1,n)ans=(ans+(i-1)*dp[j]%mod)%mod;
rep(j,2,n)rep(x,k+1,n)dp2[j]=(dp2[j]+A(n-x,j-2)*fac[n-j]%mod*k%mod)%mod;
rep(i,1,n)rep(j,i+1,n)ans=(ans+dp2[j])%mod;
}
O(n^2) solution
仍然继续优化上述式子,发现计算的瓶颈是预处理,拎出预处理式子
通过第一、二、三个子任务。
void On2sol(){
rep(j,3,n){
int sum=0;s[0]=A(0,j-3);//注意A(0,j-3)也是可能有取值的
rep(i,1,n)s[i]=(s[i-1]+A(i,j-3))%mod;
rep(z,1,k)sum=(sum+(s[n-k+z-2]-(z==1?0:s[z-2])+mod)%mod*(k-z)%mod)%mod;
dp[j]=sum*fac[n-j]%mod;
}
rep(i,2,n)rep(j,i+1,n)ans=(ans+(i-1)*dp[j]%mod)%mod;
rep(j,2,n)rep(x,k+1,n)dp2[j]=(dp2[j]+A(n-x,j-2)*fac[n-j]%mod*k%mod)%mod;
rep(i,1,n)rep(j,i+1,n)ans=(ans+dp2[j])%mod;
}