首页 > 其他分享 >AtCoder Beginner Contest 282(G 填坑dp)

AtCoder Beginner Contest 282(G 填坑dp)

时间:2023-01-16 22:12:39浏览次数:65  
标签:AtCoder Beginner Contest int sum 填坑 110 dp 位为

G - Similar Permutation

题目大意:

如果两个排列A = (A\(_1\),A\(_2\),A\(_3\)....A\(_N\)),B = (B\(_1\),B\(_2\),B\(_3\)....B\(_N\))满足:
(A\(_i\)-A\(_{i+1}\))(B\(_i\)-B\(_{i+1}\))>0 (1<= i <= N-1)
则称排列A,B的相似度为满足条件的i的数量。
现在给定n,k,p求长度为n的排列A,B,相似度为k的排列数量(mod p);


解题思路:

填坑dp:考虑一个排列在第i位填第j小的数满足条件的数量为k [dp[i][j][k]] (需要注意的是这里的条件基本都是相邻两位满足什么条件,否则不能应用)
dp[i][j][a][b]:在第i位,考虑满足条件的有j组,A填第a大的数,B填第b大的数;

我们考虑每次填当前的最后一位,如果要产生贡献(即使得j+1),那么有两种可能:

  1. A:第i位为a,第i-1位为[1~a-1]
    B:第i为为b,第i-1位为[1~b-1]
    此时(A\(_i\)-A\(_{i-1}\))>0 && (B\(_i\)-B\(_{i-1}\))>0
  2. A:第i位为a,第i-1位为[a+1~n]
    B:第i为为b,第i-1位为[b+1~n]
    此时(A\(_i\)-A\(_{i-1}\))<0 && (B\(_i\)-B\(_{i-1}\))<0

如果不产生贡献则同样有两种可能:

  1. A:第i位为a,第i-1位为[1~a-1]
    B:第i为为b,第i-1位为[b+1~n]
    此时(A\(_i\)-A\(_{i-1}\))>0 && (B\(_i\)-B\(_{i-1}\))<0
  2. A:第i位为a,第i-1位为[a+1,n]
    B:第i为为b,第i-1位为[1~b-1]
    此时(A\(_i\)-A\(_{i-1}\))<0 && (B\(_i\)-B\(_{i-1}\))>0

所以我们可以得到转移方法:

  1. 如果产生贡献:f[i][j+1][a][b] = \(\sum_{x=1}^{x=a-1}\)\(\sum_{y=1}^{y=b-1}\)f[i-1][j][x][y] + \(\sum_{x=a+1}^{x=n}\)\(\sum_{y=b+1}^{y=n}\)f[i-1][j][x][y]
  2. 如果不产生贡献:f[i][j][a][b] = \(\sum_{x=a+1}^{x=n}\)\(\sum_{y=1}^{y=b-1}\)f[i-1][j][x][y] + \(\sum_{x=1}^{x=a-1}\)\(\sum_{y=b+1}^{y=n}\)f[i-1][j][x][y]

此时我们可以看到实际上\(\sum\)\(\sum\)这一部分实际上就是二维前缀和,同时对于第i位的值只与第i-1位有关,所以可以用滚动数组优化,所以总的时间复杂度就是O(n\(^4\))

滚动数组:f[2][N][N][N],f[cur]当前状态,f[cur^1]上一位的状态


代码实现:

#include<bits/stdc++.h>
using namespace std;
# define int long long
# define endl "\n"
const int N = 2e5 + 10, inf = 1e18;
int f[2][110][110][110];
void solve() {
	int n, need, p;
	cin >> n >> need >> p;

	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			f[0][0][i][j] = 1;
		}
	}

	int cur = 0;
	vector<vector<int>> pre(n + 2, vector<int>(n + 2));
	for (int i = 2; i <= n; ++i) {
		cur ^= 1;
		memset(f[cur], 0, sizeof f[cur]);
		for (int j = 0; j < i-1; ++j) {
			for (int a = 1; a < i; ++a) {
				for (int b = 1; b < i; ++b) {
					(f[cur ^ 1][j][a][b] += f[cur ^ 1][j][a - 1][b] + f[cur ^ 1][j][a][b - 1] - f[cur ^ 1][j][a - 1][b - 1]) %= p;
				}
			}
			for (int a = 1; a <= i; ++a) {
				for (int b = 1; b <= i; ++b) {
					(f[cur][j][a][b] += f[cur ^ 1][j][i - 1][b - 1] - f[cur ^ 1][j][a - 1][b - 1] + f[cur ^ 1][j][a - 1][i - 1] - f[cur ^ 1][j][a - 1][b - 1] + p) %= p;
				}
			}
			for (int a = 1; a <= i; ++a) {
				for (int b = 1; b <= i; ++b) {
					(f[cur][j + 1][a][b] += f[cur ^ 1][j][a - 1][b - 1] + f[cur ^ 1][j][i - 1][i - 1] - f[cur ^ 1][j][a - 1][i - 1] - f[cur ^ 1][j][i - 1][b - 1] + f[cur ^ 1][j][a - 1][b - 1] + p) %= p;
				}
			}
		}
	}
	int ans = 0;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			(ans += f[cur][need][i][j] + p) %= p;
		}
	}
	cout << ans << endl;

}
int tt;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	tt = 1;
//	cin >> tt;
	while (tt--) solve();


	return 0;
}

标签:AtCoder,Beginner,Contest,int,sum,填坑,110,dp,位为
From: https://www.cnblogs.com/empty-y/p/17055242.html

相关文章

  • AtCoder Regular Contest 153(持续更新)
    PrefaceB题粗糙了改了好几个版本,最后索性从头理了一遍思路才过然后剩下40min想C又歪了(构造题精通的被动消失了),还剩25min的时候忍不住了看LPL去了话说现在的ARC感觉和以......
  • AtCoder Beginner Contest 285
    AtCoderBeginnerContest285题目来源A-EdgeChecker2题意判断一个完全二叉树,两个节点是否直接相连分析\(a=b*2或者a=b*2+1(a<b)a、b\)相连voidsolve(){ ......
  • AtCoder Beginner Contest 285 ——D
    题目:D-ChangeUsernames(atcoder.jp)题解:在所有的s[i]和t[i]之间连接一条有向边,由s[i]指向t[i],连接完之后可以发现,会形成若干条链或者环,如果出现了环那么一定不可以实......
  • Atcoder ABC285 赛后总结
    A—EdgeChecker2传送门题目大意给你一棵树,输入两个\(1-15\)的数\(a,b\),求\(a\)是否是\(b\)老爹父亲这颗树如图:题目解法超级无敌暴力法(wu一种最最最简......
  • AtCoder Beginner Contest 285 题解
    比赛链接:https://atcoder.jp/contests/abc285总体来说不算难。A-C略。\(D\)因为起点终点不同,起点之间、终点之间两两不同,所以有环的情况是错的,其他都是对的。写起来的......
  • AtCoder Beginner Contest 285 解题报告
    AtCoderBeginnerContest285解题报告\(\text{DaiRuiChen007}\)ContestLinkA.EdgeChecker2假设\(a\geb\),当且仅当\(\left\lfloor\dfraca2\right\rfloor=b\)......
  • AtCoder Beginner Contest 285 D - Change Usernames(拓扑排序)
    这题想到可以用map容器将string与一个端点下标对应,再建一个有向图,将问题转换成判断一个有向图是否有环赛后补题网上搜如何判断图是否有环,学到了拓扑排序拓扑排序是什么......
  • Atcoder ARC 061 题解
    C-ManyFormulas题意​ 给出一个长度为10的由数字组成的字符串,你可以把'+'插入到任意位置,将字符串分割,形成一个算式。你有很多分割的方案,现在你需要将所有出现的算式的......
  • AtCoder Beginner Contest 285
    A-EdgeChecker2(abc285a)题目大意给定如下一棵树。给定\(a,b(a<b)\),问两者是否有连边。解题思路观察数可发现其为二叉树,两者有连边当且仅当\(b=2a\)或\(b=2a......
  • Atcoder Regular Contest ARC 153 A B C D 题解
    点我看题A-AABCDDEFE一个beautifulnumber是形如这样的:\(S1S1S3S4S5S5S7S8S7\)。如果选定了\(S1\),后面的数有100000种选法,所以先求出答案的\(S1\)。假设现在我们要求出......