[ARC160C] Power Up

题目描述:

给出一个大小为 N 的可重集 A={ A1,A2,,AN }

你可以执行若干次如下操作(也可以不执行)。

  • 将两个 x 合并成一个 x+1

输出最终可能的集合个数对 998244353 取模的结果。

数据范围:

1N2×105

1Q2×105

思路:

实话实说,我觉得这个题其实没有那么好做。

首先一开始我就犯了一个审题错误:我误以为是必须两个相邻的才能合并


然后我们回归正题。思考这个题目中的这个问题该怎么处理。

我们发现,似乎当前这轮的个数只与上一轮的有关系,所以我们考虑令 dpi,j 表示当前枚举到了 i 这个数,并且有 ji 存在的序列的个数

然后转移也是简单的 dpi,j+ai=k=2×jlstdpi1,k 其中 lst 表示上一轮最多有多少的 i1

然后我们对这个式子进行一个变形,使其变得好看一点 dpi,j=k=2×(jai)lstdpi1,k

这样我们就可以使用后缀和优化这个式子了。

最后需要注意的是,因为最后的 mx 最终最多拥有 log2n 的个数,所以需要增加 log2n 次循环。


然后我们分析一下复杂度:

首先空间复杂度可以通过滚动数组优化到 O(N)

时间复杂度比较奇怪,他应该是类似于 n×(1+12+14+18+)2×n

所以时间复杂度 O(2n) 左右。

#include<bits/stdc++.h> using namespace std; #define int long long const int maxn=2e6+5; const int mod=998244353; const int inf=0x3f3f3f3f; int n; int a[maxn]; int bul[maxn],sum[maxn],dp[maxn]; signed main(){ cin>>n; for(int i=1;i<=n;i++)cin>>a[i],bul[a[i]]++; int mn=n,mx=0; for(int i=1;i<=n;i++)mn=min(mn,a[i]),mx=max(mx,a[i]); int lst=bul[mn]; for(int i=lst;i>=0;i--)sum[i]=1; for(int i=mn+1;i<=mx+20;i++){ lst=bul[i]+lst/2; for(int j=0;j<bul[i];j++)dp[j]=0; for(int j=bul[i];j<=lst;j++)dp[j]=sum[(j-bul[i])*2]; sum[lst]=dp[lst]; for(int j=lst-1;j>=0;j--)sum[j]=(sum[j+1]+dp[j])%mod; } cout<<sum[0]<<endl; return 0; }

__EOF__

本文作者Candycar
本文链接https://www.cnblogs.com/Candycar/p/17835093.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Candycar  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示