首页 > 其他分享 >[ABC273G] Row Column Sums 2 题解

[ABC273G] Row Column Sums 2 题解

时间:2023-03-05 12:57:37浏览次数:60  
标签:return Column 题解 times ABC273G int define dp MOD

[ABC273G] Row Column Sums 2 Solution

目录

更好的阅读体验戳此进入

题面

给定 $ n $,给定序列 $ R_n, C_n $,求有多少个 $ n \times n $ 的矩阵满足第 $ i $ 行的数之和为 $ R_i $,第 $ i $ 列的数之和为 $ C_i $,保证 $ 0 \le R_i, C_i, \le 2 $,答案对 $ 998244353 $ 取模。

Solution

提供一种较为好理解且转移较为好实现的做法,核心思路来自 @sssmzy。

设计状态 $ dp(i, j, k) $ 表示考虑前 $ i $ 行剩余 $ j $ 列需要再添 $ 1 \(,\) k $ 列需要再添 $ 2 $ 的方案数,考虑对于每一行可以去消除一些 $ j $ 或 $ k $,考虑转移:

对于 $ R_i = 0 $,显然无法产生贡献。

\[R_i = 0 : dp(i, j, k) \leftarrow dp(i - 1, j, k) \]

对于 $ R_i = 1 $,考虑要么将其补全一个 $ j $,要么将其去补到 $ k $ 使得减少一个 $ k $ 并多一个 $ j $。

\[R_i = 1 : dp(i, j, k) \leftarrow dp(i - 1, j + 1, k) \times (j + 1) + dp(i - 1, j - 1, k + 1) \times (k + 1) \]

对于 $ R_i = 2 $,考虑可以补全两个 $ j $,或补全一个 $ k $,或将两个 $ k $ 转化为两个 $ j $,或补全一个 $ j $ 并将一个 $ k $ 转换为 $ j $。

\[R_i = 2 : dp(i, j, k) \leftarrow dp(i - 1, j + 2, k) \times {j + 2 \choose 2} + dp(i - 1, j, k + 1) \times (k + 1) + dp(i - 1, j - 2, k + 2) \times {k + 2 \choose 2} + dp(i - 1, j, k + 1) \times (k + 1) \times j \]

此为 $ \texttt{3D0D} \(,考虑在每一层转移中,\) j + k $ 的值应为固定的,于是当我们已知 $ j $ 时 $ k $ 就是固定的,具体来说维护一个 $ \sum C_i $,然后每次转移时删去当前次贡献的 $ R_i $ 即可。于是以此可以无需枚举最后一维(同理也可以选择删去 $ i $ 或 $ j $),优化为 $ \texttt{2D0D} $,可以通过。

Tips:注意需要特判 $ \sum R_i \neq \sum C_i $ 时无解,答案为 $ 0 $。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW void* Edge::operator new(size_t){static Edge* P = ed; return P++;}
#define ROPNEW_NODE void* Node::operator new(size_t){static Node* P = nd; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

#define MOD (998244353ll)

template < typename T = int >
inline T read(void);

int N;
ll sumC(0);
ll dp[5100][5100];
int R[5100], C[5100];
int cnt1(0);

int main(){
    // freopen("in.txt", "r", stdin);
    N = read();
    for(int i = 1; i <= N; ++i)R[i] = read();
    for(int i = 1; i <= N; ++i)sumC += (C[i] = read());
    for(int i = 1; i <= N; ++i)if(C[i] == 1)++cnt1;
    dp[0][cnt1] = 1;
    for(int i = 1; i <= N; ++i){
        sumC -= R[i];
        for(int j = 0; j <= N; ++j){
            if((sumC - j) & 1)continue;
            int k = (sumC - j) >> 1;
            switch(R[i]){
                case 0:{
                    dp[i][j] = dp[i - 1][j];
                    break;
                }
                case 1:{
                    (dp[i][j] += dp[i - 1][j + 1] * (j + 1) % MOD) %= MOD;
                    if(j - 1 >= 0)(dp[i][j] += dp[i - 1][j - 1] * (k + 1) % MOD) %= MOD;
                    break;
                }
                case 2:{
                    (dp[i][j] += dp[i - 1][j + 2] * ((j + 2) * (j + 1) / 2 % MOD) % MOD) %= MOD;
                    (dp[i][j] += dp[i - 1][j] * (k + 1) % MOD) %= MOD;
                    if(j - 2 >= 0)(dp[i][j] += dp[i - 1][j - 2] * ((k + 2) * (k + 1) / 2 % MOD) % MOD) %= MOD;
                    (dp[i][j] += dp[i - 1][j] * (k + 1) % MOD * j % MOD) %= MOD;
                    break;
                }
            }
        }
    }
    printf("%lld\n", sumC ? 0 : dp[N][0]);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

UPD

update-2023_02_20 初稿

标签:return,Column,题解,times,ABC273G,int,define,dp,MOD
From: https://www.cnblogs.com/tsawke/p/17180238.html

相关文章

  • 力扣第335场周赛补题题解
    目录1.递枕头2.二叉树中的第K大层和3.分割数组使乘积互质4.获得分数的方法数1.递枕头classSolution{public:intpassThePillow(intn,inttime){......
  • [ABC274E] Booster 题解
    [ABC274E]BoosterSolution目录[ABC274E]BoosterSolution更好的阅读体验戳此进入题面SolutionCodeUPD更好的阅读体验戳此进入题面在经典的TSP问题基础上存在初始......
  • 题解:【ABC292F】 Regular Triangle Inside a Rectangle
    题目链接不妨设\(a\leb\)。显然当三角形三个点都在矩形边上的时候可以得到答案。通过手玩我们可以发现,当正方形推广到矩形的过程中,我们将一边拉长,三角形就可以不断往......
  • 题解 CF1406D【Three Sequences】
    看错题了,我很生气。problemYouaregivenasequenceof$n$integers$a_1,a_2,\ldots,a_n$.Youhavetoconstructtwosequencesofintegers$b$and$c......
  • LeetCode 29. Divide Two Integers 题解教程 All In One
    LeetCode29.DivideTwoIntegers题解教程AllInOnehttps://leetcode.com/problems/divide-two-integers/description///functiondivide(dividend:number,divis......
  • AGC051E[Middle Point] 题解
    条件转化我们记:\[M=\{x|x=\frac{a}{2^b},a,b\in\mathbb{Z}\}\\M^*=\{x|x\inM,x\ge0\}\]令下文向量均为二维向量,记给定点集为\({\vec{p_n}}\)那么原题即为求满足\(......
  • Java Swing项目使用Idea UI Designer设计插件无法启动问题解决方案
    起因最近整理一下以前写的swing项目,结果发现跑不起来了,具体表现为与视图表绑定的Java类的各属性为NULL(插件没有初始化绑定的类对象),导致项目无法启动。(报空指针异常)问题排......
  • CF1789D Serval and Shift-Shift-Shift 题解
    题目链接题目分析首先,看到题目中的左移右移之后再异或,我们自然可以想到在移动的过程中字符串的一段前缀和后缀不会改变,考虑通过这个性质逐位还原。因为异或0不会改变......
  • 题解 P3455 [POI2007]ZAP-Queries
    题目link是莫比乌斯函数还是莫比乌斯反演捏?感觉好多所谓“莫比乌斯反演”题只要拿\(\mu\)性质给暴力替换一下就能做出来了,比如这题qwq答案是这个式子:\(\sum\limits_{......
  • 萌新也能看懂的 Golang 题解(一)
    写在前面关于“模拟题”和“算法题”及主观难度评价第一批1791.设备编号(模拟)1792.服务器集群网络延时(排序、数学)1793.给定差值的组合(哈希表)1787.最长元音子串(模......