ARC120F-Wine Thief(非F2)——序列化环
F - Wine Thief
给定一个长度为 nnn 的序列 aaa ,从中选两两不相邻的 kkk 个数,价值为这 kkk 个数的和,求所有合法方案的价值总和对 998244353998244353998244353 取模。
2≤n≤3e5,1≤k≤⌈n2⌉2\le n\le 3e5,1\le k\le \lceil \frac{n}{2}\rceil2≤n≤3e5,1≤k≤⌈2n⌉ 。
思路
多亏了 这篇博客 的启发。
首先想到把每个数的贡献分开求,设 G(n,k,i)G(n,k,i)G(n,k,i) 表示 nnn 个数中选 kkk 个,必须选第 iii 个数的合法方案数,那么答案就是
∑i=1nai∗G(n,k,i)\sum_{i=1}^na_i*G(n,k,i) i=1∑nai∗G(n,k,i)
然而 G(n,k,i)G(n,k,i)G(n,k,i) 非常不好求,因为要考虑每个数前面和后面选了多少个。如果能够找到每个 G(n,k,i)G(n,k,i)G(n,k,i) 之间的数量关系就可以先求出其中一个值继而求出其余所有。
根据经验,我们可以通过把序列化成环达到这个目的 (经验就是不讲道理) 。
如果把序列化成环,那么就只多了一个限制: a1a_1a1 和 ana_nan 不能同时选。
我们把 G(n,k,i)G(n,k,i)G(n,k,i) 的定义放到环上变为 G′(n,k,i)G'(n,k,i)G′(n,k,i) ,那么由于环上的方案旋转同构,所以对于任意 iii , G′(n,k,i)G'(n,k,i)G′(n,k,i) 是相等的。
为了方便,我们定义 f(n,k)f(n,k)f(n,k) 为 nnn 个数中选 kkk 个数的方案数,那么把数与数之间的空去掉,可得 f(n,k)=Cn−k+1kf(n,k)=C_{n-k+1}^{k}f(n,k)=Cn−k+1k ;定义 G′(n,k,i)=F(n,k)G'(n,k,i)=F(n,k)G′(n,k,i)=F(n,k) ,讨论一下可得 F(n,k)={[k==1]n<3f(n−3,k−1)n≥3F(n,k)=\left\{\begin{matrix}[k==1] & n<3\\ f(n-3,k-1) & n≥3\end{matrix}\right.F(n,k)={[k==1]f(n−3,k−1)n<3n≥3 。
现在我们考虑把这个限制去掉,那么只需要加上 a1a_1a1 和 ana_nan 同时选的情况。而这种情况相当于固定了两端的四个点,而中间的 n−4n-4n−4 个点又构成了一个子问题,所以我们可以得到 G(n,k,i)G(n,k,i)G(n,k,i) 的递推式:
G(n,k,i)={0i≤0F(n,k)+f(n−4,k−2)i=1F(n,k)+G(n−4,k−2,i−2)i>1G(n,k,n−i+1)i>⌈n2⌉G(n,k,i)=\left\{\begin{matrix} 0 & i\le 0 \\F(n,k)+f(n-4,k-2) & i=1 \\F(n,k)+G(n-4,k-2,i-2) & i>1 \\G(n,k,n-i+1) & i>\lceil\frac{n}{2}\rceil \end{matrix}\right. G(n,k,i)=⎩⎪⎪⎨⎪⎪⎧0F(n,k)+f(n−4,k−2)F(n,k)+G(n−4,k−2,i−2)G(n,k,n−i+1)i≤0i=1i>1i>⌈2n⌉
现在问题的症结就在如何快速求 i>1i>1i>1 的情况,通过把它展开,我们发现
G(n,k,i)=F(n,k)+F(n−4,k−2)+F(n−8,k−4)+...G(n,k,i)=F(n,k)+F(n-4,k-2)+F(n-8,k-4)+... G(n,k,i)=F(n,k)+F(n−4,k−2)+F(n−8,k−4)+...
因此,对于不同的 iii , G(n,k,i)G(n,k,i)G(n,k,i) 的前面部分完全一样,我们只需要预处理出前缀和,然后对每个 G(n,k,i)G(n,k,i)G(n,k,i) 特判一次即可。
现在唯一的问题就是,这么递归下去求值的时候,很可能会出现算组合数里其中一个参数小于0的情况,而这种情况在上面的所有式子中都是没有意义的,所以取0即可。
剩下的代码就非常好打了,只要把每个函数里写好就行。常数随便大,因为是 O(n)O(n)O(n) 。
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#include<map>
#define ll long long
#define MAXN 300005
#define uns unsigned
#define INF 0x7f7f7f7f
#define lowbit(x) ((x)&(-(x)))
#define MOD 998244353ll
using namespace std;
inline ll read(){ll x=0;bool f=1;char s=getchar();while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();return f?x:-x;
}
inline ll ksm(ll a,ll b,ll mo){ll res=1;for(;b;b>>=1,a=a*a%mo)if(b&1)res=res*a%mo;return res;
}
int n,k,D;
ll a[MAXN],fac[MAXN],inv[MAXN];
inline ll C(int n,int m){if(m<0||m>n)return 0;return fac[n]*inv[m]%MOD*inv[n-m]%MOD;
}
inline ll gf(int n,int k){return C(n-k+1,k);}
inline ll gF(int n,int k){if(n<3)return k==1;else return gf(n-3,k-1);
}
ll sf[MAXN];
inline ll G(int n,int k,int i){if(i<1)return 0;else if(i==1)return (gF(n,k)+gf(n-4,k-2))%MOD;else if(i>((n+1)>>1))return G(n,k,n-i+1);else return (sf[i>>1]+G(n-((i>>1)<<2),k-((i>>1)<<1),i&1))%MOD;
}
int main()
{n=read(),k=read(),D=read();for(int i=1;i<=n;i++)a[i]=read();fac[0]=fac[1]=inv[0]=inv[1]=1;for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%MOD;inv[n]=ksm(fac[n],MOD-2,MOD);for(int i=n-1;i>1;i--)inv[i]=inv[i+1]*(1ll+i)%MOD;for(int i=1;i<=n;i++)sf[i]=(sf[i-1]+gF(n-((i-1)<<2),k-((i-1)<<1)))%MOD;ll ans=0;for(int i=1;i<=n;i++)ans=(ans+a[i]*G(n,k,i)%MOD)%MOD;printf("%lld\n",ans);return 0;
}
ARC120F-Wine Thief(非F2)——序列化环相关推荐
- HDU4514(非连通图的环判断与图中最长链)
题目:设计风景线 题意:给定一个无向图,图可能是非连通的,如果图中存在环,就输出YES,否则就输出图中最长链的长度. 分析:首先我们得考虑这是一个无向图,而且有可能是非连通的,那么就不能直接像求树那样 ...
- Python基础知识点拾遗---文件IO(os、filecmp、shutil库)、sys库、序列化(pickle)、类
Python基础知识点拾遗 文件IO 文本 目录 os 获取文件的创建.修改及最近访问时间 获取当前文件的大小 获取当前的登录用户名称 获取当前的cpu核数 调用操作系统底层的random生成器 sh ...
- Binder相关面试总结(五):为什么Activity间传递对象需要序列化
前言 我们都知道进行Android 开发的时候,跳转到Activity和Fragment的时候,传递对象是通过Intent或者bundle 进行传递.当这个对象没有实现序列化的时候 当你通过Inetn ...
- 序列化和反序列化的对单例破坏的防止及其原理
首先我们来看一下序列化和反序列化是怎么破坏单例的.看代码 public class HungrySingleton implements Serializable{private final stat ...
- 浅析SQL Server在可序列化隔离级别下,防止幻读的范围锁的锁定问题
本文出处:http://www.cnblogs.com/wy123/p/7501261.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些 ...
- Android | 序列化Serializable/Parcelable 使用总结
本文已同步发表于我的微信公众号,搜索 代码说 即可关注,欢迎与我沟通交流. 文章目录 一.什么是序列化?为什么要序列化?怎么进行序列化? 二.Serializable 2.1 序列化举例 2.2 重写 ...
- android对象序列化的方法,Android 进阶-两种序列化方式 Serializable 和 Parcelable
[导读]序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区中读取或反序列化对象的状态 ...
- ImmutableList hessian2序列化失败问题分析
问题描述 A服务提供了个RPC接口给B服务使用,入参里有个参数是List类型,B服务在传参时使用Guava里的 ImmutableList,结果发生报错. 其中,B服务即consumer端的异常为:「 ...
- 几种Java序列化方式的实现
0.前言 本文主要对几种常见Java序列化方式进行实现.包括Java原生以流的方法进行的序列化.Json序列化.FastJson序列化.Protobuff序列化. 1.Java原生序列化 Java原生 ...
- GAP4.7/4.10.2软件中尚不完善的有限环功能
GAP4没有与IdGroup对应的IdRing命令: 例如: for j in [1..2] do for i in [1..11] do R:=DirectSum(SmallRing(4,i),Sm ...
最新文章
- 每天一道LeetCode-----找到给定序列中所有和为某个值的集合或集合个数,序列中可以有/无重复项,集合元素顺序不同算不同集合等
- 【C语言】输出半径1到10的圆的面积,当面积值超过100时,停止执行本程序
- python random模块
- python 放射 水平_基于Python的放射性核素大气扩散程序初步开发与验证
- sap期初导资产代码_SAP S/4固定资产导入期初科目设置
- 操作系统文件的物理结构(文件分配方式)
- Android ViewPager 如何判断当前页面是从前一页还是后一页滑动过来
- 云服务器抢票咋用_可以利用云服务器来抢票不?
- 电子章怎么做(电子公章怎么生成),只要三步
- Warning: require(E:\oms\public/../vendor/autoload.php): failed to open stream: No such file or direc
- mysql:mysql数据库下载及安装(详细)
- Mac环境配置SSH Key
- Handler之创建子线程Handler
- 诚之和:李子柒向资本发起“反击战”
- 乘法器的实现(阵列、Booth、Wallace)
- 液体效果,制作喷溅的液态裙子教程
- 全站写作平台疯传24小时删除
- Python 远程操作 Linux
- 微信小程序使用api接受数据
- java解析Epub,按照1级目录拆分epub文件