有一個序列 \(a_1,a_2,\ldots,a_n\),有 \(q\) 次操做,每次操做給你兩個數 \(x,y\),你能夠交換 \(a_x,a_y\),或者什麼都不作。dom
問你全部 \(2^q\) 種狀況中逆序對的個數之和。spa
\(n,q\leq 3000\)code
考慮對於每一對 \(i,j\),計算 \(q\) 次操做後 \(a_i\) 和 \(a_j\) 的大小關係。get
記 \(f_{i,j,k}\) 爲操做 \(i\) 次後,\(a_j,a_k\) 這對數中較小的在 \(j\),較大的在 \(k\) 的機率。string
每次操做只會修改 \(O(n)\) 個位置的DP值。it
時間複雜度:\(O(n^2+qn)\)io
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<ctime> #include<functional> #include<cmath> #include<vector> #include<assert.h> //using namespace std; using std::min; using std::max; using std::swap; using std::sort; using std::reverse; using std::random_shuffle; using std::lower_bound; using std::upper_bound; using std::unique; using std::vector; typedef long long ll; typedef unsigned long long ull; typedef double db; typedef std::pair<int,int> pii; typedef std::pair<ll,ll> pll; void open(const char *s){ #ifndef ONLINE_JUDGE char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout); #endif } void open2(const char *s){ #ifdef DEBUG char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout); #endif } int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;} void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');} int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;} int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;} const int N=3010; const ll p=1000000007; ll fp(ll a,ll b) { ll s=1; for(;b;b>>=1,a=a*a%p) if(b&1) s=s*a%p; return s; } const ll inv2=fp(2,p-2); int a[N]; int n,q; ll f[N][N]; int main() { open2("d"); scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(a[i]<a[j]) f[i][j]=1; int x,y; for(int i=1;i<=q;i++) { scanf("%d%d",&x,&y); f[x][y]=f[y][x]=(f[x][y]+f[y][x])*inv2%p; for(int j=1;j<=n;j++) if(j!=x&&j!=y) { f[x][j]=f[y][j]=(f[x][j]+f[y][j])*inv2%p; f[j][x]=f[j][y]=(f[j][x]+f[j][y])*inv2%p; } } ll ans=0; for(int i=1;i<=n;i++) for(int j=1;j<i;j++) ans=(ans+f[i][j])%p; ans=ans*fp(2,q)%p; ans=(ans%p+p)%p; printf("%lld\n",ans); return 0; }