首页 > 其他分享 >【题解】[Codechef] Beautiful Permutation

【题解】[Codechef] Beautiful Permutation

时间:2024-10-18 16:59:28浏览次数:7  
标签:Beautiful cnt 奇数 题解 sum k2 Permutation dp mod

传送门

以此纪念我场切的 dp。

这种计数的类型一看就很 dp 的样子。考场上一开始设的 dp 状态是 \(dp_{i,j,k_1,k_2,0/1}\) 表示将前 \(i\)个数分为 \(j\) 段,放了 \(k_1\) 个偶数,\(k_2\) 个奇数,当前段为偶数段或奇数段的方案数。考虑如何转移,记 \(cnt_0\) 表示序列中可填入的偶数个数,\(cnt_1\) 表示序列中可填入的奇数个数。

当 \(i\) 为空时,可以写出四个转移:

\[dp_{i,j,k_1,k_2,0} = (cnt_0-k_1+1)(dp_{i-1,j,k_1-1,k_2,0} + dp_{i-1,j-1,k_1-1,k_2,1}) \]

\[dp_{i,j,k_1,k_2,1}=(cnt_1-k_2+1)(dp_{i-1,j,k_1,k_2-1,1} + dp_{i-1,j-1,k_1,k_2-1,0}) \]

当 \(i\) 为非空时,可以根据 \(a_i\) 的奇偶性写出两个转移:

\[dp_{i,j,k_1,k_2,0} = dp_{i-1,j,k_1,k_2,1} + dp_{i-1,j-1,k_1,k_2,0} (a_i 为奇数) \]

\[dp_{i,j,k_1,k_2,1} = dp_{i-1,j-1,k_1,k_2,1} + dp_{i-1,j,k_1,k_2,0} (a_i 为偶数) \]

可以把第一维滚掉,这样就做到了时间复杂度 \(O(n^4)\),空间复杂度 \(O(4n^3)\)。70分到手。

我们发现记前 \(i\) 个数中空位为 \(sum_i\) 个,则填了 \(k_2\) 个奇数时必然填了 \(sum_i-k_2\) 个偶数。偶数的数量可以被奇数固定下来,于是重新设状态 \(dp_{i,j,k_2,0/1}\) 表示将前 \(i\)个数分为 \(j\) 段,\(k_2\) 个奇数,当前段为偶数段或奇数段的方案数。则转移变为:

当 \(i\) 为空时:

\[dp_{i,j,k_2,0} = (cnt_0-(sum_i-k_2)+1)(dp_{i-1,j,k_2,0} + dp_{i-1,j-1,k_2,1}) \]

\[dp_{i,j,k_2,1}=(cnt_1-k_2+1)(dp_{i-1,j,k_2-1,1} + dp_{i-1,j-1,k_2-1,0}) \]

当 \(i\) 为非空时:

\[dp_{i,j,k_2,0} = dp_{i-1,j,k_2,1} + dp_{i-1,j-1,k_2,0} (a_i 为奇数) \]

\[dp_{i,j,k_2,1} = dp_{i-1,j-1,k_2,1} + dp_{i-1,j,k_2,0} (a_i 为偶数) \]

时间复杂度为 \(O(n^3)\),空间复杂度 \(O(2n^3)\)。可通过此题。

#include<bits/stdc++.h>
#define int long long
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)
#define mod 1000000007

using namespace std;

const int N = 305;

int n, m, a[N], cnt[N], dp[N][N][N][2], sum;

signed main() {
  freopen("2475.in", "r", stdin);
  freopen("2475.out", "w", stdout);
  ios::sync_with_stdio(0);
  cin.tie(0), cout.tie(0);
  cin >> n >> m;
  For(i,1,n) {
    cin >> a[i];
    if(!a[i]) continue;
    cnt[a[i] & 1]++;
  }
  cnt[0] = n / 2 - cnt[0];
  cnt[1] = ceil(1.0 * n / 2) - cnt[1];
  dp[0][0][0][0] = dp[0][0][0][1] = 1;
  For(i,1,n) {
    if(!a[i]) sum++;
    For(j,1,m) {
      For(k2,0,min(sum, cnt[1])) {
        if(a[i] != 0) {
          if(a[i] & 1) {
            dp[i][j][k2][1] = (dp[i][j][k2][1] + (dp[i-1][j-1][k2][0] + dp[i-1][j][k2][1]) % mod) % mod;
          } else {
            dp[i][j][k2][0] = (dp[i][j][k2][0] + (dp[i-1][j][k2][0] + dp[i-1][j-1][k2][1]) % mod) % mod;
          }
          continue;
        }
        if(cnt[0] - (sum - k2) + 1 > 0) dp[i][j][k2][0] = (dp[i][j][k2][0] + ((cnt[0] - (sum - k2) + 1) * (dp[i-1][j-1][k2][1] + dp[i-1][j][k2][0]) % mod) % mod) % mod;
        if(k2 != 0) dp[i][j][k2][1] = (dp[i][j][k2][1] + ((cnt[1] - k2 + 1) * (dp[i-1][j-1][k2-1][0] + dp[i-1][j][k2-1][1]) % mod) % mod) % mod;
      }
    }
  }
  cout << (dp[n][m][cnt[1]][0] + dp[n][m][cnt[1]][1]) % mod << '\n';
  return 0;
}

标签:Beautiful,cnt,奇数,题解,sum,k2,Permutation,dp,mod
From: https://www.cnblogs.com/Daniel-yao/p/18474614

相关文章

  • 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......
  • P9351 [JOI 2023 Final] Maze 题解
    Description给定一张\(R\timesC\)的地图,其中.可以走,而#不能走。一次操作可以将\(N\timesN\)的正方形范围内所有点变成.,给定起点和终点,求最少需要几次操作使得起点和终点连通(只能上下左右移动)。\(R\timesC\le6\times10^6\),\(N\leR\leC\)。Solution先考虑怎么......
  • CF571B-题解
    CF571B题意给定数组\(A\)和值\(k\),你可以重排\(A\)中的元素,使得\(\displaystyle\sum_{i=1}^{n-k}|A_i-A_{i+k}|\)最小。输出最小值。思路\(A_i,A_{i+k}\)就等同于在将\(i\)模\(k\)的意义上把\(A\)分为若干组贪心的想要使\(\displaystyle\sum_{i=1}^{n-k}|A_i-A......
  • 【题解】Solution Set - NOIP2024集训Day56 哈希杂题
    【题解】SolutionSet-NOIP2024集训Day56哈希杂题https://www.becoder.com.cn/contest/5640「CF568C」NewLanguage做过的2-sat。「NOI2024」集合做过。做法见提交记录。「CSP-S2022」星战简要题意:给定有向图。修改使一条边失效/恢复;使一个点的所有入边......
  • [YDOI R1] Necklace 题解
    题目传送门前置芝士二项式定理:\((a+b)^n=\sum\limits_{i=0}^{n}C^i_n\timesa^i\timesb^{n-i}\)快速幂Meaning有\(n\)种珠子,每种有\(a_i\)颗,且美丽值为\(v_i\)。任意两颗珠子不同(同种类也算不同)。每种珠子有一个漂亮值\(v_i\)。项链有一个美丽度,若第\(i\)种珠子......
  • Codeforces Round 893 (Div. 2)题解记录
    题目链接:https://codeforces.com/contest/1858A.Buttons从自身角度出发,我想赢就得保证我的按钮尽可能多所以,大家都优先按\(c\),然后分析先后顺序即可 #include<iostream> #include<string.h> #include<map> #include<vector> #include<set> #include<unordered_set> #......
  • [ABC134F] Permutation Oddness 题解
    [ABC134F]PermutationOddness题解朴素的想法显然是状压dp,枚举选择的子集,但复杂度不可接受。考虑优化。注意到对于\(p_i\),它的贡献只会有两种可能性,\(+p_i,-p_i\)。于是初步的想法是按照\(p_i\)的正负性选择分类。考虑到对于相同正负性的选择\(p\),其是等价的。于是我们......
  • P4229 某位歌姬的故事 题解
    P4229某位歌姬的故事题解\(n\le9\times10^8\),显然复杂度不与\(n\)相关。\(m\le500\),显然可以接受\(O(Tm^2)\)的做法。对于\([l,r]\),考虑套路地将端点离散化,使得复杂度只和关键点个数有关。考虑对于\([l,r,m]\),离散化后被分成了\(a_1,a_2,\cdots,a_p\)段,那么这些段的......