首页 > 其他分享 >[ABC134F] Permutation Oddness 题解

[ABC134F] Permutation Oddness 题解

时间:2024-10-18 21:48:26浏览次数:1  
标签:Oddness 盒子 题解 当前 情况 配对 ABC134F 2j

T5 [ABC134F] Permutation Oddness

很无敌的一道题。(好像是我第一次用无敌这个词

把 \(p_i\) 和 \(i\) 的对应关系转化为球和盒子的配对问题,则原式中的绝对值顺利成章地就变成类似距离的一个东西。

那么设 \(f_{i,j,k}\) 表示前 \(i\) 个球和盒子(注意球和盒子是一起考虑的,所以 \(i\) 只会遍历到 \(n\))、其中有 \(j\) 球和盒子暂未配对、当前怪异度为 \(k\) 的答案。则答案为:\(f_{n,0,K}\)。到这里应该是不难理解的。

考虑新遍历到一组球和盒子,会有三种情况出现:不给它们配对、给其中一个配对、给俩都配对。

情况一:不给它们配对。

则易得转移方程:

\[f_{i+1,j+1,k+2j}\gets f_{i,j,k} \]

\(k+2j\) 是什么?以后再解释。

情况二:给其中一个配对。

  1. 如果给球配对,相当于用了之前的一个没有配对的盒子,有 \(j\) 种情况;
  2. 如果给盒子配对,相当于用了之前的一个没有配对的球,有 \(j\) 种情况;
  3. 还有一种特殊情况:直接将当前球和当前盒子配成一对,有 \(1\) 种情况。

综上,有 \(2j+1\) 种情况。易得任意一种都是用了一个没有配对的又多了一个当前的,或者是直接解决当前的且不管前面的,所以 \(j\) 不变,有转移方程:

\[f_{i+1,j,k+2j}\gets f_{i,j,k}\times(2j+1) \]

情况三:给俩都配对。

当前的球有 \(j\) 个盒子给它配对,当前的盒子也有 \(j\) 个球给它配对,共 \(j^2\) 种方案。由于这种情况直接消耗了两个(也就是一组)没有配对的球和盒子,所以转移方程长这样:

\[f_{i+1,j-1,k+2j}\gets f_{i,j,k}\times j^2 \]

那么问题来了,为什么是 \(k+2j\) 呢?

我们可以理解为:状态中的 \(j\) 有另一种解释,\(1\sim i\) 的这些球有 \(j\) 个要放到编号大于 \(i\) 的盒子里。那么如果把第 \(i\) 组球和盒子处理完了,也就是将前 \(j\) 个球和盒子中的一个配上对了,那么剩下的就要都再往下配对一行,导致总共多出了 \(2j\) 的贡献。

这篇题解对 \(k+2j\) 的解释更加详细。

#include<bits/stdc++.h>
#define fw fwrite(obuf,p3-obuf,1,stdout)
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
#define putchar(x) (p3-obuf<1<<20?(*p3++=(x)):(fw,p3=obuf,*p3++=(x)))
using namespace std;

char buf[1<<20],obuf[1<<20],*p1=buf,*p2=buf,*p3=obuf,str[20<<2];
int read(){
	int x=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x;
}
template<typename T>
void write(T x,char sf='\n'){
	if(x<0)putchar('-'),x=~x+1;
	int top=0;
	do str[top++]=x%10,x/=10;while(x);
	while(top)putchar(str[--top]+48);
	if(sf^'#')putchar(sf);
}
using ll=long long;
constexpr int MAXN=55,MOD=1e9+7;
int n,K;
int dp[MAXN][MAXN][MAXN*MAXN];
void add(int&x,int y){
	x=x+y>=MOD?x+y-MOD:x+y;
}

int main(){
	n=read(),K=read();
	if(K&1)return write(0),fw,0;
	dp[0][0][0]=1;
	for(int i=0;i<n;++i)
		for(int j=0;j<=i;++j)
			for(int k=0;k<=K;++k){
				add(dp[i+1][j][k+2*j],(ll)dp[i][j][k]*(j<<1|1)%MOD);
				if(j)add(dp[i+1][j-1][k+2*j],(ll)dp[i][j][k]*j%MOD*j%MOD);
				add(dp[i+1][j+1][k+2*j],dp[i][j][k]);
			}
	write(dp[n][0][K]);
	return fw,0;
}

标签:Oddness,盒子,题解,当前,情况,配对,ABC134F,2j
From: https://www.cnblogs.com/laoshan-plus/p/18475122

相关文章

  • [ARC185D] Random Walk on Tree 题解
    一个很套路的做法。思路题目要求走完整个树的时间,这并不好算,容易想到min-max容斥。依据min-max容斥,我们可以轻松把它转化成第一次走到所有子集的时间。考虑在这道题中,有什么特殊的。第一,任何包含根节点的子集答案都是零。第二,由于我们只关心第一次走到的点的时间,因此假......
  • ZZJC新生训练赛第五场题解
    A题思路题目要求构造一个相邻两项互质的长度为n的序列。可以直接选择输出从1到n的自然数序列,因为相邻的自然数总是互质的。题目有多个测试用例,因此需要逐个处理输入,并输出对应结果。代码#include<bits/stdc++.h>usingnamespacestd;intmain(){ios::sync_wit......
  • 题解:[YNOI2019] 游戏
    ProblemLink[YNOI2019]游戏题外话第一眼,由乃?不打不打。第二眼,欸noi三个字母怎么是大写(才发现是云南省选)。题意题意简洁,不再赘述。Solution一眼看出概率dp,但如何似乎没思路?开始公式做题:设置状态+推转移式。\(Q1\):怎么设置状态?首先,思考一个问题:第\(k\)个人该怎么“......
  • 异常问题解决
    异常:java程序编译或运行过程中出现的问题Throwable:Error:表示非常严重的问题,自己无法解决的问题Exception:除了RuntimeException其它异常【编译时期异常】:一般指的是异常尚未处理就编译了RuntimeException【运行时期异......
  • PTA L1系列题解(C语言)(L1_081 -- L1_088)
    L1-081今天我要赢题目内容:2018年我们曾经出过一题,是输出“2018我们要赢”。今年是2022年,你要输出的句子变成了“我要赢!就在今天!”然后以比赛当天的日期落款。输入格式:本题没有输入。输出格式:输出分2行。在第一行中输出I'mgonnawin!Today!,在第二行中用年年年......
  • P1955 程序自动分析 题解
    P1955程序自动分析一道并查集的裸题,并查集存储传递性,后判断。主题思路十分简单,重点在于离散化与离线的处理。离散化,为什么会想到离散化呢,观察数据范围\(1<i,j<{10}^9\),数据范围过大,导致数组不可能开到\(1e9\)但是\(1<n<1e5\)考虑到每次输入只有两个数,若每个数都两两不同,......
  • 【题解】[Codechef] Beautiful Permutation
    传送门以此纪念我场切的dp。这种计数的类型一看就很dp的样子。考场上一开始设的dp状态是\(dp_{i,j,k_1,k_2,0/1}\)表示将前\(i\)个数分为\(j\)段,放了\(k_1\)个偶数,\(k_2\)个奇数,当前段为偶数段或奇数段的方案数。考虑如何转移,记\(cnt_0\)表示序列中可填入的偶数......
  • Codeforces Round 892 (Div. 2)题解记录
    题目链接:https://codeforces.com/contest/1859A.UnitedWeStand选最大的数即可注意题目输出格式 #include<iostream> #include<string.h> #include<map> #include<vector> #include<set> #include<unordered_set> #include<stack> #incl......
  • P5025 [SNOI2017] 炸弹 题解
    题意link.题解一个好想一点的正解。考虑到可能连锁爆炸,我们不能通过一个单纯的二分来解决问题。考虑dp。记\(f(i)\)为第\(i\)个点爆炸,最远能引爆到哪个坐标小于它的点。\(g(i)\)为第\(i\)个点爆炸,最远能引爆到哪个坐标大于它的点。我们以\(f\)为例,\(g\)可以通......
  • AT_nikkei2019_2_qual_c 题解
    blog。不会做结论题,怎么办???不会做结论题,怎么办???不会做结论题,怎么办???不妨对\(b\)排序,将\(a\)对应到相应的位置。那么题目有两个条件:#1:\(\foralla_i\leb_i\)。#2:操作限制。注意到\(n-1\)次操作就能完成对\(a\)排序。所以用\(n-2\)次操作可以将\(a\)变成一个Almos......