zoukankan      html  css  js  c++  java
  • agc030_d Inversion Sum

    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;
    }
    
    
  • 相关阅读:
    [Android]SharedPreferences
    [Android]XML界面布局常用属性概括
    [Android]XML解析技术
    [Android]Layout标签之-viewStub,requestFocus,merge,include
    [Android]JSON
    [Android]SQLite基本控制台命令简介
    [Android]流文件
    [HTML5]WebSQLDatabase-关系型数据库简介
    [Android]ADB和NavicatLiteSQLDBmanager的数据管理
    [Android]SqliteOpenHelper抽象类实现SQL_DB的管理
  • 原文地址:https://www.cnblogs.com/YouthRhythms/p/14221435.html
Copyright © 2011-2022 走看看