首页 > 其他分享 >CF1874F Jellyfish and OEIS

CF1874F Jellyfish and OEIS

时间:2024-09-27 22:23:59浏览次数:1  
标签:排列 OEIS CF1874F int 区间 长度 Jellyfish mod

CF1874F Jellyfish and OEIS

第一次独立切 *3500,写篇题解记录一下

我们称 \([l,r]\) 为一个排列,当且仅当 \([p_l,p_{l+1},\dots,p_r]\) 为 \([l,l+1,\dots,r]\) 的一个排列。

不妨固定 \(l\),我们只需要考虑最小的 \(r\) 满足 \([l,r]\) 为一个排列。考虑每个 \([l,r]\) 所构成的区间,如果 \([l_1,r_1],[l_2,r_2]\) 相交且不包含,不妨设 \(l_1<l_2\le r_1<r_2\),那么 \([l_2,r_1]\) 必然为一个排列,与定义矛盾,所以所有 \([l,r]\) 区间构成一个树形结构。

设 \(f_{i,j}\) 表示 \(i\) 的对应最小的 \(j\) 满足 \([i,j]\) 为一个排列,且满足 \([i,j]\) 中的所有的限制的方案数。一个暴力的转移是枚举其中若干不交区间的 \(f\) 的乘积,为 \([i,j]\) 在树上的下一层,设其长度和为 \(L\),那么还需要乘上 \(h_{j-i+1-L}\) 进行加和,其中 \(h_n\) 表示长度为 \(n\) 的排列满足除了 \([1,n]\) 的所有子区间不为排列。

设 \(g_{i,j,k}\) 表示 \([i+1,j]\) 中选取若干区间的 \(f\) 的乘积,满足区间长度和为 \(k\),这个可以在按照长度递增 dp \(f\) 时顺便更新,目前 dp 到的长度为 \(len\),那么就可以更新所有 \(g_{i,i+len-1,k}\) 。

\(h\) 考虑容斥,钦定 \(i\) 个不相交的区间,表示这 \(i\) 个区间为对应的 \(l\) 的最小的 \(r\),那么每个区间内部的方案为 \(h_{len}\),每次需要再设 \(a_{i,j}\) 表示前 \(i\) 个数中钦定区间总长度为 \(j\),转移时带上 \((-1)\) 的容斥系数。对于没有钦定的 \(n-j\) 个数可以随便填,方案数为 \((n-j)!\) 。

最后需要把若干 \(f\) 进行合并,设 \(b_i\) 表示目前合并到 \(i\),枚举 \(j\),转移为 \(b_i=\sum\limits_{j=1}^{i}b_{i-j}f_{i-j+1,i}\) 。

至此,\(g\) 的转移是 \(\mathcal{O}(n^4)\) 的,\(f,h\) 的转移是 \(\mathcal{O}(n^3)\) 的,那么总复杂度就是 \(\mathcal{O}(n^4)\) 的。

实现时显然常数很小,所以 \(n=200\) 可以过。

#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int N = 205, mod = 1e9 + 7;

void add(int & x, int y) {x += y; if (x >= mod) x -= mod;}
void dec(int & x, int y) {x += mod - y; if (x >= mod) x -= mod;}
int pls(int x, int y) {x += y; if (x >= mod) x -= mod; return x;}
int sub(int x, int y) {x += mod - y; if (x >= mod) x -= mod; return x;}
int mul(int x, int y) {return 1ll * x * y % mod;}

int n, m[N], f[N][N], g[N][N][N], h[N], fac[N], a[N][N], b[N];

bool END;

signed main() {
  cin >> n; for (int i = 1; i <= n; ++i) cin >> m[i];
  fac[0] = 1; for (int i = 1; i <= n; ++i) fac[i] = mul(fac[i - 1], i);
  h[1] = 1;
  for (int i = 2; i <= n; ++i) {
    memset(a, 0, sizeof a), a[0][0] = 1;
    for (int j = 1; j <= i; ++j) {
      for (int k = 0; k <= j; ++k) {
	a[j][k] = a[j - 1][k];
	for (int l = 1; l <= min(i - 1, k); ++l)
	  dec(a[j][k], mul(a[j - l][k - l], h[l]));
      }
    }
    for (int j = 0; j <= i; ++j) add(h[i], mul(a[i][j], fac[i - j]));
  }
  for (int i = 1; i <= n; ++i) f[i][i] = (m[i] < i), f[i + 1][i] = g[i][i - 1][0] = 1;
  h[1] = 0;
  for (int len = 2; len <= n; ++len)
    for (int i = 1; i + len - 1 <= n; ++i) {
      int j = i + len - 1;
      for (int k = 0; k <= j - i; ++k) {
	add(g[i + 1][j][k], g[i + 1][j - 1][k]);
	for (int l = 1; l <= k; ++l) add(g[i + 1][j][k], mul(g[i + 1][j - l][k - l], f[j - l + 1][j]));
      }
      if (j > m[i]) {
	for (int k = 0; k <= j - 1 - i; ++k) {
	  add(f[i][j], mul(g[i + 1][j - 1][k], h[len - k]));
	}
      }
    }
  b[0] = 1;
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= i; ++j)
      add(b[i], mul(b[i - j], f[i - j + 1][i]));
  }
  cout << b[n] << endl;
  return 0;
}

标签:排列,OEIS,CF1874F,int,区间,长度,Jellyfish,mod
From: https://www.cnblogs.com/Tagaki-san/p/18436708

相关文章

  • C. Jellyfish and Green Apple
    原题链接题解1.由于是除二操作,所以最后的平均数一定能表示成\(k_1\cdot\frac{1}{2^{i_1}}+...+k_t\cdot\frac{1}{2^{i_t}}\)的形式2.最小的\(\frac{1}{2^i}\)由于没有往下再分,所以数量一定是偶数,把他们的数量除二加到\(\frac{1}{2^{i-1}}\)上,此时\(i-1\)就变最小的了......
  • D. Jellyfish and Mex
    题目:链接:https://codeforces.com/problemset/problem/1875/D思路:这题刚开始没啥想法,后面推演了一下发现是个动态规划:从左到右先找出首先为0的点,那么我要求的值就是这个区间内的值。然后假设先把ax清为0,那么所加的值就是ax*ptr,对比发现就是上一阶段的小规模。所以可以用递推......
  • A. Jellyfish and Game
    原题链接题解1.经过样例证明,双方的交换策略一定是自己最小值去换对面最大值2.双方交换的最大值一定局限在双方各自初始最大值之间,最小值也是code#include<bits/stdc++.h>#definelllonglongusingnamespacestd;intmain(){llt;cin>>t;while(t--)......
  • Jellyfish and EVA
    这道题目实在没有什么好的办法去描述状态空间,只能感性理解一下,等对概率的理解更深了再来吧。。。发现这是一道概率DP,而且满足拓扑序,我们直接倒序转移就好了设\(f_i\)表示从第\(i\)个点到第\(n\)个点的概率,我们发现当只有一条出边是非常好转移的,但是其他就不太行了我们遇到这种......
  • CF1874F 做题记录
    link太绝了。首先容易想到要用容斥,具体的,我们钦定区间集合\(S=\{[l,r]|p_{l...r}\text{是}l...r\text{的排列}\}\),贡献为\((-1)^{|S|}\)乘上对应方案数。然后仔细观察,不难发现对于选出来的区间\([l_1,r_1],[l_2,r_2]\),若满足\(l_1<l_2<r_1<r_2\),则\([l_1,l_2-1],[l_2,r......
  • CodeForces 1874E Jellyfish and Hack
    洛谷传送门CF传送门显然\(\text{fun}(P)_{\max}=\frac{|P|(|P|+1)}{2}\)。考虑大力dp,设\(f_{i,j,k}\)为\(|P|=i\),\(P_1=j\),\(\text{fun}(P)=k\)的排列\(P\)的个数。此时\(|L|=j-1,|R|=i-j\)。转移枚举\(L_1,R_1,\text{fun}(L),\text{fun}(R......
  • 13 Jellyfish and Game
    JellyfishandGame因为n,m很小,所有直接暴力就行#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;voidsolve(){ intn,m,k; cin>>n>>m>>k; vector<int>a(n+1); vector<int>b(m+1); for(inti=1;i<=n;i++)cin>......
  • 12 Jellyfish and Green Apple
    JellyfishandGreenApple数论将苹果平均的分给人,可以将苹果一分为二,问你最少分多少次。首先把能分的都分掉就是n%=m,其次操作数是很好想的,就一直*2并且%m,直到n==0,关于这题有难度的就是n,m分不了的情况。设想一下,成功的情况,也就是这个n一直在乘2最后能==m。那么转换一下就是......
  • Jellyfish and OEIS
    JellyfishandOEIS题意题面传送门题解恭恭敬敬给致远磕大头。首先我们将原序列分割成很多块,使得每一块都是相对位置的排列。且这一块内不可分割出另外的块。例如:\([3,1,2][5,4]\),而\([1,2,3]\)是不合法的,因为他可以被分割为\([1][2][3]\)。在进行这一步操作之后,我们发......
  • 1-1875D - Jellyfish and Mex
    题意:有一个长度为\(n\)的数组,每次删除一个数直到删完,求每次删除后数组的mex的和的最小值。(\(\sumn\leq5000,a_i\leq10^9\))思路:排序后,只有从0开始连续的数在会有贡献,对于连续的数,如果要消去他的对答案的贡献,只有全部去掉才行,考虑n的范围小于5000,n^2做法被允许。//因为排......