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∑n​ai​∗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)——序列化环相关推荐

  1. HDU4514(非连通图的环判断与图中最长链)

    题目:设计风景线 题意:给定一个无向图,图可能是非连通的,如果图中存在环,就输出YES,否则就输出图中最长链的长度. 分析:首先我们得考虑这是一个无向图,而且有可能是非连通的,那么就不能直接像求树那样 ...

  2. Python基础知识点拾遗---文件IO(os、filecmp、shutil库)、sys库、序列化(pickle)、类

    Python基础知识点拾遗 文件IO 文本 目录 os 获取文件的创建.修改及最近访问时间 获取当前文件的大小 获取当前的登录用户名称 获取当前的cpu核数 调用操作系统底层的random生成器 sh ...

  3. Binder相关面试总结(五):为什么Activity间传递对象需要序列化

    前言 我们都知道进行Android 开发的时候,跳转到Activity和Fragment的时候,传递对象是通过Intent或者bundle 进行传递.当这个对象没有实现序列化的时候 当你通过Inetn ...

  4. 序列化和反序列化的对单例破坏的防止及其原理

    首先我们来看一下序列化和反序列化是怎么破坏单例的.看代码 public class HungrySingleton implements Serializable{private final stat ...

  5. 浅析SQL Server在可序列化隔离级别下,防止幻读的范围锁的锁定问题

    本文出处:http://www.cnblogs.com/wy123/p/7501261.html  (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些 ...

  6. Android | 序列化Serializable/Parcelable 使用总结

    本文已同步发表于我的微信公众号,搜索 代码说 即可关注,欢迎与我沟通交流. 文章目录 一.什么是序列化?为什么要序列化?怎么进行序列化? 二.Serializable 2.1 序列化举例 2.2 重写 ...

  7. android对象序列化的方法,Android 进阶-两种序列化方式 Serializable 和 Parcelable

    [导读]序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区中读取或反序列化对象的状态 ...

  8. ImmutableList hessian2序列化失败问题分析

    问题描述 A服务提供了个RPC接口给B服务使用,入参里有个参数是List类型,B服务在传参时使用Guava里的 ImmutableList,结果发生报错. 其中,B服务即consumer端的异常为:「 ...

  9. 几种Java序列化方式的实现

    0.前言 本文主要对几种常见Java序列化方式进行实现.包括Java原生以流的方法进行的序列化.Json序列化.FastJson序列化.Protobuff序列化. 1.Java原生序列化 Java原生 ...

  10. 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 ...

最新文章

  1. 每天一道LeetCode-----找到给定序列中所有和为某个值的集合或集合个数,序列中可以有/无重复项,集合元素顺序不同算不同集合等
  2. 【C语言】输出半径1到10的圆的面积,当面积值超过100时,停止执行本程序
  3. python random模块
  4. python 放射 水平_基于Python的放射性核素大气扩散程序初步开发与验证
  5. sap期初导资产代码_SAP S/4固定资产导入期初科目设置
  6. 操作系统文件的物理结构(文件分配方式)
  7. Android ViewPager 如何判断当前页面是从前一页还是后一页滑动过来
  8. 云服务器抢票咋用_可以利用云服务器来抢票不?
  9. 电子章怎么做(电子公章怎么生成),只要三步
  10. Warning: require(E:\oms\public/../vendor/autoload.php): failed to open stream: No such file or direc
  11. mysql:mysql数据库下载及安装(详细)
  12. Mac环境配置SSH Key
  13. Handler之创建子线程Handler
  14. 诚之和:李子柒向资本发起“反击战”
  15. 乘法器的实现(阵列、Booth、Wallace)
  16. 液体效果,制作喷溅的液态裙子教程
  17. 全站写作平台疯传24小时删除
  18. Python 远程操作 Linux
  19. 微信小程序使用api接受数据
  20. java解析Epub,按照1级目录拆分epub文件

热门文章

  1. 清新漂亮简约好看的个人博客网站模板
  2. EDM邮件营销需要开展多久才能取得最佳的营销效果
  3. 深度指纹识别:通过深度学习破坏网站指纹防御
  4. dub的sdl配置文件中文帮助
  5. centos网卡配置
  6. python-pygame实现飞机大战-4-获取补给、发射强化子弹以及放大招清屏
  7. 在计算机中汉字能否排序,你不得不知的Excel表格中汉字多种排序方法
  8. 什么是域名?什么网站名?什么是URL?
  9. ActiveMq简单使用
  10. android锁屏显示