CF1740F Conditional Mix

题目大意

有一个正整数 n n n和一个长度为 n n n的序列 a a a, 1 ≤ a i ≤ n 1\leq a_i\leq n 1≤ai​≤n。

把每个 a i a_i ai​看成一个一元集 { a i } \{a_i\} {ai​},每次可以合并两个交集为空的集合。可以经过任意次合并。设合并完每个集合的元素个数组成可重集为 S S S,求 S S S的种类数,输出答案模 998244353 998244353 998244353。

1 ≤ n ≤ 2000 1\leq n\leq 2000 1≤n≤2000

题解

首先我们通过补 0 0 0将这个可重集内元素个数变为 n n n。不妨设可重集内的元素是从大到小的。

对于可重集内两个位置 i , j i,j i,j,若其对应的集合的大小为 A i A_i Ai​和 A j A_j Aj​且 A i > A j A_i>A_j Ai​>Aj​,那么集合 A i A_i Ai​中必定有一个元素可以取出并放到 A j A_j Aj​。也就是说,对于两个可重集 A A A和 B B B,如果满足 ∀ 1 ≤ k ≤ n \forall1\leq k\leq n ∀1≤k≤n都满足 ∑ i = 1 k A i ≤ ∑ i = 1 k B i \sum\limits_{i=1}^kA_i\leq \sum\limits_{i=1}^kB_i i=1∑k​Ai​≤i=1∑k​Bi​,那么如果 A A A合法,则 B B B也合法。

那么,对于每一个 k k k,我们只需要找到 ∑ i = 1 k A i \sum\limits_{i=1}^{k}A_i i=1∑k​Ai​的上界即可。如果一个数出现次数小于等于 k k k,那肯定都能选;如果出现次数大于 k k k,则最多只能取 k k k次。设 c n t i cnt_i cnti​表示 i i i出现的次数,那么 ∑ i = 1 k A i ≤ ∑ i = 1 k min ⁡ ( k , c n t i ) \sum\limits_{i=1}^kA_i\leq \sum\limits_{i=1}^k\min(k,cnt_i) i=1∑k​Ai​≤i=1∑k​min(k,cnti​)。接下来,问题就转化为满足条件的可重集 A A A的个数。

我们从大到小选数。设 f i , j , k f_{i,j,k} fi,j,k​表示可重集中已经选了前 i i i个数,这 i i i个数的和为 j j j,可重集中最小的元素大于等于 k k k。那么转移如下

f i , j , k = f i , j , k + 1 + [ j ≥ k ] × f i − 1 , j − k , k f_{i,j,k}=f_{i,j,k+1}+[j \geq k]\times f_{i-1,j-k,k} fi,j,k​=fi,j,k+1​+[j≥k]×fi−1,j−k,k​

转移为 O ( 1 ) O(1) O(1)的,但时间复杂度和空间复杂度为 O ( n 3 ) O(n^3) O(n3)。我们考虑优化。

对于空间,我们可以用滚动数组来省去一维。

设当前可重集中的元素分别为 A 1 , A 2 , … , A i A_1,A_2,\dots,A_i A1​,A2​,…,Ai​,显然 A 1 , A 2 , … , A i ≥ k A_1,A_2,\dots,A_i\geq k A1​,A2​,…,Ai​≥k,所以 ∑ j = 1 i A j ≥ i × k \sum\limits_{j=1}^iA_j\geq i\times k j=1∑i​Aj​≥i×k。又因为 ∑ j = 1 i A j ≤ n \sum\limits_{j=1}^iA_j\leq n j=1∑i​Aj​≤n,所以 i × k ≥ n i\times k\geq n i×k≥n,即 k ≤ n i k\leq \dfrac ni k≤in​。也就是说,每次枚举 k k k的时间复杂度为 O ( n i ) O(\dfrac ni) O(in​),那么总时间复杂度为 O ( n 2 ln ⁡ n ) O(n^2\ln n) O(n2lnn)。

code

#include<bits/stdc++.h>
using namespace std;
const int N=2000;
int n,x,cnt[2005],w[2005];
long long ans,f[2][2005][2005];
long long mod=998244353;
bool cmp(int ax,int bx){return ax>bx;
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&x);++cnt[x];}sort(cnt+1,cnt+n+1,cmp);for(int k=1;k<=n;k++){for(int i=1;i<=n;i++) w[k]+=min(k,cnt[i]);}for(int i=0;i<=n;i++) f[0][0][i]=1;for(int i=1,e=1;i<=n;i++,e^=1){for(int j=0;j<=w[i];j++){f[e][j][n/i+1]=0;}for(int k=n/i;k>=0;k--){for(int j=0;j<=w[i];j++){f[e][j][k]=f[e][j][k+1];if(j>=k) f[e][j][k]=(f[e][j][k]+f[e^1][j-k][k])%mod;}}}printf("%lld",f[n&1][n][0]);return 0;
}

CF1740F Conditional Mix相关推荐

  1. 英语的第0 1 2 3 条件句 zero conditional sentence

    链接:https://www.zhihu.com/question/356888479/answer/903039736 条件句分真实条件句和非真实条件句 非真实条件句也叫虚拟条件句. 第1条件句属于 ...

  2. 使用Jittor实现Conditional GAN

    Jittor实现Conditional GAN Generative Adversarial Nets(GAN)提出了一种新的方法来训练生成模型.然而,GAN对于要生成的图片缺少控制.Conditio ...

  3. 风格化手绘纹理包 CGTrader – Stylized Mix Vol. 41 – Hand Painted Texture Pack

    风格化手绘纹理包 CGTrader – Stylized Mix Vol. 41 – Hand Painted Texture Pack CGTrader–风格化混合第41卷–手绘纹理包 大小解压后: ...

  4. [WCF REST] 解决资源并发修改的一个有效的手段:条件更新(Conditional Update)

    条件获取(Conditional Update)可以避免相同数据的重复传输,进而提高性能.条件更新(Conditional Update)用于解决资源并发操作问题.如果我们预先获取一个资源进行修改或者 ...

  5. SpringBoot conditional注解和自定义conditional注解使用

    conditional注解是Springboot starter的基石,自动装配的时候会根据条件确定是否需要注入这个类. 含义:基于条件的注解. 作用:根据是否满足某个特定条件来决定是否创建某个特定的 ...

  6. 【Qt】启动QtCreator时报错:Cannot mix incompatible Qt library (version ) with this library (version...

    1.问题描述 当启动QtCreator时报错(我的Qt版本是Qt5.6.3): Cannot mix incompatible Qt library (version 0x50603) with th ...

  7. SpringBoot复习:3(@Conditional)

    @Conditional 条件装配:满足@Conditional指定的条件时,则进行组件注入 @Conditional注解下面包含许多注解,如下图: 这些注解各有各的功能,这里挑几个来记录一下. @C ...

  8. 改善代码设计 —— 简化条件表达式(Simplifying Conditional Expressions)

    系列博客 1. 改善代码设计 -- 优化函数的构成(Composing Methods) 2. 改善代码设计 -- 优化物件之间的特性(Moving Features Between Objects) ...

  9. AI一分钟 | 小米MIX 2S将于3月27号发布,搭载骁龙845;张朝阳:在研究区块链 但相信AI的力量

    一分钟AI 华为确认P20系列即将登陆巴黎,AI加成拍照功能更出色 张朝阳:在研究区块链,但相信AI的力量 Waymo无人车新专利,根据乘客身体状况选择合适的路线,可为易晕车乘客选择平坦路线 新款 A ...

最新文章

  1. Unity C# Sting.Format的学习
  2. caxa画图怎么倒角_16个底部含圆弧倒角的宽槽编程案例
  3. 如何在php中写内容,请问如何在内容模板中写标题和内容呢
  4. Swarm的进化和大规模应用
  5. OAuth和OpenID的区别
  6. 公募权益类基金投资者盈利洞察报告
  7. mysql 指定ip段 掩码_IP分配及网段划分
  8. win8需要计算机管理员权限才能删除,win8系统使用管理员权限无法删除部分文件怎么办...
  9. Android音视频学习思路整理
  10. 设计物联网系统的步骤和原则有哪些
  11. 管家婆设计页面用什么做的_管家婆软件主要是用来做什么的?
  12. 运放搭建电压电流转换电路分析
  13. “风味人间”与计算机程序设计艺术《禅与计算机程序设计艺术》
  14. 使用Python播放MIDI音符
  15. Android facebook集成
  16. Oracle中根据注释来查表名
  17. 一个强迫症的电脑上(桌面篇)
  18. 关于《机器学习实战》中创建决策树的核心代码分析
  19. 【总结】初创公司用AWS搭建高扩展性架构
  20. C# 后台生成二维码图片

热门文章

  1. MW75蓝牙5.2双模热插拔PCB
  2. 转:干货 :手把手教你Tableau高级数据分析功能(附数据集)
  3. iOS开发判断当前系统版本
  4. 对于语句:f=(3.0,4.0,5.0),(2.0,1.0,0.0);的判断中,( )是正确的。
  5. unity快速开发问答游戏(二)
  6. 2019上半年休闲手游买量报告:投放量激增 买量效果不一
  7. Ubuntu安装anaconda做英文词云
  8. oracle的基本概念
  9. 计算某年有多少周(周的起始日期。结束日期)
  10. [Erlang]如何使用NIF