arc103_d
题目叙述
agc030_d
题目叙述
给出一个排列 (p_1cdots p_n) ,再给出 (Q) 次操作,每次操作是交换 (x_i) 和 (y_i) 两个位置上的数。每个操作可以选择执行或者不执行,但是所有执行的操作必须按照给出的顺序执行。求所有情况逆序对数量的综合。
题解
考虑到逆序对数量为 (sum_{i=1}^{n-1}sum_{j=i+1}^n[a_i>a_j]) 。考虑将这题的所有情况的逆序对数量之和转化为逆序对期望大小与 (2^Q) 的乘积。
由于期望的线性性,(Eleft(sum_{i=1}^{n-1}sum_{j=i+1}^n[a_i>a_j] ight)=sum_{i=1}^{n-1}sum_{j=i+1}^nEleft([a_i>a_j] ight)) 。考虑枚举 (i) 和 (j) ,然后考虑 (f_{x,y,z}) 表示 (Q) 次操作中的前 (x) 次,(a_i) 现在的位置是 (y) ,(a_j) 的位置是 (z) 的概率。可以发现,转移只有 (mathcal O(n)) 个位置会改变(指 (f_{x,y,z}) 到 (f_{x+1,y,z}) 不同的位置只有 (mathcal O(n)) 个)。这样就得到了一个 (mathcal O(n^4)) 级别的算法(默认 (n,q) 同阶)。
然后考虑到这转移是线性的,即不会出现 (f_i=f_{i-1}^2+3) 类似的情况,又发现不同 (i,j) 对应的 (f_{x,y,z}) 的区别只是初始值,转移方式完全相同。所以可以直接将所有初始值加起来,然后合起来直接进行 ( t dp) 。因为一些细节原因,需要进行两次 ( t dp) 。
代码
(mathcal O(n^4)) 做法:
#include <cstdio>
using namespace std;
const int NN = 3e3 + 5, Mod = 1e9 + 7;
const int INV2 = (Mod + 1) / 2;
int Ad(int x, int y) { return ((x + y) > Mod) ? (x + y - Mod) : (x + y); }
int Ml(int x, int y) { return (long long)x * y % Mod; }
int N, Q, x[NN], y[NN], a[NN];
int dp[NN][NN], r0[NN], r1[NN], c0[NN], c1[NN];
int main() {
scanf("%d%d", &N, &Q);
for (int i = 1; i <= N; ++i)
scanf("%d", &a[i]);
for (int i = 1; i <= Q; ++i)
scanf("%d%d", &x[i], &y[i]);
int ans = 0;
int pro = 1;
for (int i = 1; i <= Q; ++i)
pro = Ml(pro, 2);
for (int i = 1; i <= N; ++i) {
for (int j = i + 1; j <= N; ++j) {
if (a[i] == a[j])
continue ;
for (int r = 1; r <= N; ++r)
for (int c = 1; c <= N; ++c)
dp[r][c] = 0;
dp[i][j] = 1;
for (int k = 1; k <= Q; ++k) {
for (int r = 1; r <= N; ++r) {
r0[r] = Ml(Ad(dp[r][x[k]], dp[r][y[k]]), INV2);
r1[r] = Ml(Ad(dp[r][y[k]], dp[r][x[k]]), INV2);
int c = r;
c0[c] = Ml(Ad(dp[x[k]][c], dp[y[k]][c]), INV2);
c1[c] = Ml(Ad(dp[y[k]][c], dp[x[k]][c]), INV2);
//r0[i]为dp[i][x[k]]
//r1[i]为dp[i][y[k]]
//c0[i]为dp[x[k]][i]
//c1[i]为dp[y[k]][i]
}
for (int r = 1; r <= N; ++r) {
if (r != y[k])
dp[r][x[k]] = r0[r];
if (r != x[k])
dp[r][y[k]] = r1[r];
int c = r;
if (c != y[k])
dp[x[k]][c] = c0[c];
if (c != x[k])
dp[y[k]][c] = c1[c];
}
int s = Ad(dp[x[k]][y[k]], dp[y[k]][x[k]]);
dp[x[k]][y[k]] = dp[y[k]][x[k]] = Ml(s, INV2);
// if (i == 1 && j == 5)
// printf("k : %d dp[x[k]][y[k]] : %d dp[y[k]][x[k]] : %d x[k] : %d y[k] : %d
", k, dp[x[k]][y[k]], dp[y[k]][x[k]], x[k], y[k]);
}
int con = 0;
for (int p = 1; p <= N; ++p)
for (int q = p + 1; q <= N; ++q) {
if (a[i] > a[j])
con = Ad(con, dp[p][q]);
else
con = Ad(con, dp[q][p]);
}
ans = Ad(ans, con);
/* if (i == 1 && j == 5) {
printf("i : %d j : %d con : %d
", i, j, Ml(con, pro));
for (int p = 1; p <= N; ++p) {
for (int q = p + 1; q <= N; ++q) {
printf("p : %d q : %d dp : %d
", p, q, Ml(dp[p][q], pro));
}
}
}*/
}
}
ans = Ml(ans, pro);
printf("%d
", ans);
return 0;
}
(mathcal O(n^2)) 做法:
#include <cstdio>
using namespace std;
const int NN = 3e3 + 5, Mod = 1e9 + 7;
const int INV2 = (Mod + 1) / 2;
int Ad(int x, int y) { return ((x + y) > Mod) ? (x + y - Mod) : (x + y); }
int Ml(int x, int y) { return (long long)x * y % Mod; }
int N, Q, x[NN], y[NN], a[NN];
int dp[NN][NN], r0[NN], r1[NN], c0[NN], c1[NN];
int ans;
void Do1() {
for (int r = 1; r <= N; ++r)
for (int c = 1; c <= N; ++c)
dp[r][c] = 0;
for (int i = 1; i <= N; ++i)
for (int j = i + 1; j <= N; ++j)
if (a[i] > a[j])
dp[i][j] = 1;
for (int k = 1; k <= Q; ++k) {
for (int r = 1; r <= N; ++r) {
r0[r] = Ml(Ad(dp[r][x[k]], dp[r][y[k]]), INV2);
r1[r] = Ml(Ad(dp[r][y[k]], dp[r][x[k]]), INV2);
int c = r;
c0[c] = Ml(Ad(dp[x[k]][c], dp[y[k]][c]), INV2);
c1[c] = Ml(Ad(dp[y[k]][c], dp[x[k]][c]), INV2);
//r0[i]为dp[i][x[k]]
//r1[i]为dp[i][y[k]]
//c0[i]为dp[x[k]][i]
//c1[i]为dp[y[k]][i]
}
for (int r = 1; r <= N; ++r) {
if (r != y[k])
dp[r][x[k]] = r0[r];
if (r != x[k])
dp[r][y[k]] = r1[r];
int c = r;
if (c != y[k])
dp[x[k]][c] = c0[c];
if (c != x[k])
dp[y[k]][c] = c1[c];
}
int s = Ad(dp[x[k]][y[k]], dp[y[k]][x[k]]);
dp[x[k]][y[k]] = dp[y[k]][x[k]] = Ml(s, INV2);
// if (i == 1 && j == 5)
// printf("k : %d dp[x[k]][y[k]] : %d dp[y[k]][x[k]] : %d x[k] : %d y[k] : %d
", k, dp[x[k]][y[k]], dp[y[k]][x[k]], x[k], y[k]);
}
int con = 0;
for (int p = 1; p <= N; ++p)
for (int q = p + 1; q <= N; ++q)
con = Ad(con, dp[p][q]);
ans = Ad(ans, con);
}
void Do2() {
for (int r = 1; r <= N; ++r)
for (int c = 1; c <= N; ++c)
dp[r][c] = 0;
for (int i = 1; i <= N; ++i)
for (int j = i + 1; j <= N; ++j)
if (a[i] < a[j])
dp[i][j] = 1;
for (int k = 1; k <= Q; ++k) {
for (int r = 1; r <= N; ++r) {
r0[r] = Ml(Ad(dp[r][x[k]], dp[r][y[k]]), INV2);
r1[r] = Ml(Ad(dp[r][y[k]], dp[r][x[k]]), INV2);
int c = r;
c0[c] = Ml(Ad(dp[x[k]][c], dp[y[k]][c]), INV2);
c1[c] = Ml(Ad(dp[y[k]][c], dp[x[k]][c]), INV2);
//r0[i]为dp[i][x[k]]
//r1[i]为dp[i][y[k]]
//c0[i]为dp[x[k]][i]
//c1[i]为dp[y[k]][i]
}
for (int r = 1; r <= N; ++r) {
if (r != y[k])
dp[r][x[k]] = r0[r];
if (r != x[k])
dp[r][y[k]] = r1[r];
int c = r;
if (c != y[k])
dp[x[k]][c] = c0[c];
if (c != x[k])
dp[y[k]][c] = c1[c];
}
int s = Ad(dp[x[k]][y[k]], dp[y[k]][x[k]]);
dp[x[k]][y[k]] = dp[y[k]][x[k]] = Ml(s, INV2);
// if (i == 1 && j == 5)
// printf("k : %d dp[x[k]][y[k]] : %d dp[y[k]][x[k]] : %d x[k] : %d y[k] : %d
", k, dp[x[k]][y[k]], dp[y[k]][x[k]], x[k], y[k]);
}
int con = 0;
for (int p = 1; p <= N; ++p)
for (int q = p + 1; q <= N; ++q)
con = Ad(con, dp[q][p]);
ans = Ad(ans, con);
}
int main() {
// freopen("AGC030D.out", "w", stdout);
scanf("%d%d", &N, &Q);
for (int i = 1; i <= N; ++i)
scanf("%d", &a[i]);
for (int i = 1; i <= Q; ++i)
scanf("%d%d", &x[i], &y[i]);
int pro = 1;
for (int i = 1; i <= Q; ++i)
pro = Ml(pro, 2);
Do1();
Do2();
ans = Ml(ans, pro);
printf("%d
", ans);
// fclose(stdout);
return 0;
}