首页 > 其他分享 >P8863 「KDOI-03」构造数组

P8863 「KDOI-03」构造数组

时间:2024-11-14 09:57:41浏览次数:1  
标签:03 frac int ll KDOI P8863 jc inv mod

P8863 「KDOI-03」构造数组

cplusoj:SS241113D. 构造数组 (array)

题意

给你一个长度为 \(n\le 5000\) 的数组 \(\{b\}\),满足 \(\sum b \le 30000\)。每次操作你可以选择两个下标 \(i,j,i \neq j\),将 \(b_i,b_j\) 减 \(1\),问有多少种操作方式使得 \(b\) 变成全部是 \(0\)。

思路

看完题解之后发现并不是很难???(

设 \(s_i = \sum_{j=1}^i b_i\),显然当 \(s_n\) 为奇数的时候答案为 \(0\),因为每次操作都会使总和减 \(2\)。

刻画一下操作,相当于一共有 \(\frac{s_n}{2}\) 个桶,每个数字需要选择 \(b_i\) 个不相同的桶,每个桶只能装 \(2\) 个数字。

其中每个数字选择的桶的顺序是不重要的,因为无论你如何顺序选桶,最终我都会按照桶的编号顺序操作。

容易想到状压。

发现每个桶其实本质相同,都是只能装两个数字,因此我们不需要即每个桶的状态。只需要记 \(k_{0/1/2}\) 表示已经装了 \(0/1/2\) 个数字的桶有多少个。

因此可以设 \(f_{i,k_0,k_1,k_2}\) 表示处理到第 \(i\) 个数字,已经装了 \(0/1/2\) 个数字的桶有 \(k_{0/1/2}\) 个,的方案数。

转移的时候,枚举第 \(i\) 个数字往 \(0/1\) 的桶里分别装了多少个桶,往已经装了 \(1\) 个数字的桶里选了 \(j\) 个桶,那么 \(0\) 的桶就选了 \(b_i-j\) 个桶。转移方程就是

\[f_{i+1,k_0-b_i+j,k_1+b_i-j-j,k_2+j} \gets \binom{k_0}{b_i-j} \binom{k_1}{j} f_{i,k_0,k_1,k_2} \]

比较显然的是我们不需要维护三个 \(k\),实际上我们只需要维护 \(1\) 个 \(k\)。

设 \(k\) 表示已经装了 \(1\) 个球的的桶有多少个。

\[\begin{cases} k_0=\frac{s_n}{2}-k_1-k_2\\ k_1=k\\ k_2=\frac{s_{i-1}-k_1}{2} \end{cases} \]

整理一下,转移式子就是

\[f_{i+1,k+b_i-2j} \gets \binom{\frac{s_n}{2}-k-\frac{s_{i-1}-k}{2}}{b_i-j} \binom{k}{j} f_{i,k} \]

状态数是 \(O(n\sum b)\) 的,好像甚至不需要滚动数组,不过滚一下也无妨,把第一维滚掉。转移的时候枚举 \(k\) 是 \(O(\sum b)\) 的,枚举 \(j\) 是 \(O(b_i)\) 的,因此复杂度 $O((\sum b)^2),可以算出来的有至少 \(\frac{1}{4}\) 的常数。

code

#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace poetry {
    constexpr int N=5e3+7,mod=998244353,M=3e4+7;
    int n,b[N],s[N];
    int jc[M],inv[M];
    int f[2][M];
    int add(int a,int b) { return a+b>=mod ? a+b-mod : a+b; }
    void _add(int &a,int b) { a=add(a,b); }
    ll ksm(ll a,ll b=mod-2) {
        ll s=1;
        while(b) {
            if(b&1) s=s*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return s;
    }
    void init() {
        jc[0]=1;
        rep(i,1,s[n]>>1) jc[i]=1ll*jc[i-1]*i%mod;
        inv[s[n]>>1]=ksm(jc[s[n]>>1]);
        per(i,(s[n]>>1)-1,0) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    }
    ll c(int n,int m) {
        if(m>n) return 0;
        return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
    }
    void main() {
        sf("%d",&n);
        rep(i,1,n) sf("%d",&b[i]);
        sort(b+1,b+n+1);
        rep(i,1,n) s[i]=s[i-1]+b[i];
        if((s[n]&1)||n==1) puts("0"), exit(0);
        if(n==2) {
            if(b[1]==b[2]) puts("1");
            else puts("0");
            exit(0);
        } 
        init();
        f[1][0]=1;
        rep(i,1,n) {
            int lim=i-2<0 ? 0 : s[i-2]+1;
            memset(f[(i&1)^1],0,sizeof(int)*lim);
            rep(k,0,s[i-1]) {
                if(f[i&1][k])
                rep(j,0,b[i]) {
                    if(k+b[i]-(j<<1)<0) break;
                    _add(f[(i&1)^1][k+b[i]-(j<<1)],c((s[n]>>1)-k-((s[i-1]-k)>>1),b[i]-j)*c(k,j)%mod*f[i&1][k]%mod);
                }
            }
        }
        pf("%d\n",f[(n+1)&1][0]);
    }
}
int main() {
    #ifdef LOCAL
    freopen("my.out","w",stdout);
    #else 
    freopen("array.in","r",stdin);
    freopen("array.out","w",stdout);
    #endif
    poetry :: main();
}

标签:03,frac,int,ll,KDOI,P8863,jc,inv,mod
From: https://www.cnblogs.com/liyixin0514/p/18545320

相关文章

  • AlignSum:数据金字塔与层级微调,提升文本摘要模型性能 | EMNLP'24
    来源:晓飞的算法工程笔记公众号,转载请注明出处论文:AlignSum:DataPyramidHierarchicalFine-tuningforAligningwithHumanSummarizationPreference论文地址:https://arxiv.org/abs/2410.00409论文代码:https://github.com/csyanghan/AlignSum创新点发现在文本......
  • B. Alice's Adventures in Permuting (python解)-codeforces
    B.Alice'sAdventuresinPermuting(python解)-codeforces原题链接:B.Alice'sAdventuresinPermuting问题分析:我们需要将数组a转换为一个排列,排列是由n个不同的整数构成,范围从0到n−1。数组a是通过给定的参数n、b和c生成的。\[a[i]=b⋅(i−1)+c\]\[对于1≤i......
  • P11103 [ROI 2022 Day 2] 挑战
    题目可以看成一个最大流模型。源点\(S\)往所有机器人连边,容量为\(c_i\);所有容器往汇点\(T\)连边,容量为\(a_i\);机器人\(i\)往容器\(j\in[l_i,r_i]\)连边,容量\(+\infty\)。最大流即为答案。最大流不好计算,考虑最小割。不妨令选取容器集合为\(S\),不被\(S\)包含的区间......
  • CICD03 Jenkins对golang项目构建, 结合ansible, 构建通知, 自动化构建(定时,webhook),
    2.7.2基于Maven风格的任务构建基于WAR包运行Tomcat服务器JAVA项目maven配置繁琐,功能固定不灵活,不如自由风格好用,这里推荐用自由风格脚本实现更好目前最高依赖到tomcat9,更高版本的tomcat不支持2.7.2.2安装tomcat服务器和配置#在gitlab新建java项目(此项目使用JD......
  • WebXR与WebGL集成开发教程_2024-07-26_15-03-25.Tex
    WebXR与WebGL集成开发教程WebXR简介WebXR的由来与优势WebXR是WebXRDeviceAPI的简称,它是一个用于在Web浏览器中创建沉浸式虚拟现实(VR)和增强现实(AR)体验的API。WebXR的设计旨在提供一个统一的接口,让开发者能够更容易地在不同的设备和平台上创建和部署XR(扩......
  • baka's trick
    众所周知,双指针适用于一类固定左端点,右端点具有单调性的问题,由于每个点只会被删一次,所以令加入/删除的时间复杂度为\(O(B)\),总时间复杂度\(O(nB)\)。而对于一些信息,加入是简单的,但是删除是困难的(例如gcd、min)等,这时我们考虑baka'strick把删除扔掉。考虑设一个阈值\(p\),假......
  • 03LangChain初学者指南:从零开始实现高效数据检索
    LangChain初学者指南:从零开始实现高效数据检索https://python.langchain.com/v0.2/docs/tutorials/retrievers/这个文档,我们将熟悉LangChain的向量存储和抽象检索器。支持从(向量)数据库和其他来源检索数据,并与大模型的工作流集成。这对于需要检索数据以进行推理的应用程序非常重......
  • avalonia在linux下运行出现Default font family name can't be null or empty问题的解
    avalonia在linux下运行出现Defaultfontfamilynamecan'tbenullorempty的错误,是因为Avalonia无法确定或找不到默认的字体名,可以先在控制台打命令确定本机安装字体fc-list然后在avalonia项目的program.cs中增加此代码:publicstaticAppBuilderBuildAvalonia......
  • SAM4MLLM:结合多模态大型语言模型和SAM实现高精度引用表达分割 | ECCV'24
    来源:晓飞的算法工程笔记公众号,转载请注明出处论文:SAM4MLLM:EnhanceMulti-ModalLargeLanguageModelforReferringExpressionSegmentation论文地址:https://arxiv.org/abs/2409.10542论文代码:https://github.com/AI-Application-and-Integration-Lab/SAM4MLLM创......
  • Illegal mix of collations for operation 'UNION' 记录错误
    24-11-12,在DVWA靶场练习回顾SQL注入union注入的时候突然发现,不管搞都报错!Illegalmixofcollationsforoperation'UNION'自己查了好久之后才发现是数据库编码不匹配的问题!!!union两端的字段的collatie(排序规则)不同参考:https://blog.csdn.net/qq_43665434/article/details/......