Inverse
1≤n≤500,0≤k≤501 ≤ n ≤ 500,0 ≤ k ≤ 501≤n≤500,0≤k≤50, P是一个1到n的排列.
概率dpdpdp好题。
思路:
定义fi,j,kf_{i,j,k}fi,j,k表示kkk轮变换之后api>apja_{p_i}>a_{p_j}api>apj的概率。
然后考虑对当前轮翻转的区间[l,r][l,r][l,r]分类转移。
- r<i or l>j or i<l<r<jr<i\ \ or\ \ l>j\ \ or\ \ i<l<r<jr<i or l>j or i<l<r<j,则fi,j,k−1→fi,j,kf_{i,j,k-1}\rightarrow f_{i,j,k}fi,j,k−1→fi,j,k
- l≤i≤r<jl\le i\le r<jl≤i≤r<j,则fl+r−i,j,k−1→fi,j,kf_{l+r-i,j,k-1}\rightarrow f_{i,j,k}fl+r−i,j,k−1→fi,j,k
- i<l≤j≤ri<l\le j\le ri<l≤j≤r,则fi,l+r−j,k−1→fi,j,kf_{i,l+r-j,k-1}\rightarrow f_{i,j,k}fi,l+r−j,k−1→fi,j,k
- l≤i<j≤rl\le i<j\le rl≤i<j≤r,则1−fl+r−j,l+r−i→fi,j,k1-f_{l+r-j,l+r-i}\rightarrow f_{i,j,k}1−fl+r−j,l+r−i→fi,j,k
利用二阶前缀和来优化转移可以做到O(n2k)O(n^2k)O(n2k)
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
typedef long long ll;
const int mod=1e9+7;
inline int add(const int&a,const int&b){
return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){
return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){
return (ll)a*b%mod;}
inline void update(int&a,const int&b){
a=a+b>=mod?a+b-mod:a+b;}
inline int ksm(int a,int p){
int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)ret=mul(ret,a);return ret;}