ARC120F Wine Thief (组合数学)
题面
有一个长为
N
N
N 的序列,相邻的两个数中只能选一个,总共选
k
k
k 个数,一种方案的价值为选的
k
k
k 个数的和,问所有合法方案的价值总和,答案对 998244353
取模。
1
≤
N
≤
3
⋅
1
0
5
,
1
≤
k
≤
⌈
N
2
⌉
1\leq N\leq 3\cdot10^5~,~1\leq k\leq \left\lceil \frac{N}{2} \right\rceil
1≤N≤3⋅105 , 1≤k≤⌈2N⌉.
题解
把每个数的贡献拆开求,答案就是 每个数的值 × 该数被选的方案数。这是最基本的转化。
令
G
(
n
,
i
,
k
)
G(n,i,k)
G(n,i,k) 表示
n
n
n 个数中选
k
k
k 个数,必选第
i
i
i 个数的方案数。
我们先鲁莽地列个式子,枚举第
i
i
i 个数前面选了多少个数,然后就是个放球问题,不难发现
G
(
n
,
i
,
k
)
=
∑
j
=
0
(
i
−
1
)
/
2
C
i
−
1
−
j
j
⋅
C
n
−
i
−
k
−
1
+
j
k
−
1
−
j
G(n,i,k)=\sum_{j=0}^{(i-1)/2}C_{i-1-j}^{j}\cdot C_{n-i-k-1+j}^{k-1-j}
G(n,i,k)=∑j=0(i−1)/2Ci−1−jj⋅Cn−i−k−1+jk−1−j
——毫无可做性。
我们得换个思路想。不妨容斥一下?先设
f
(
n
,
k
)
f(n,k)
f(n,k) 为在
n
n
n 个数中选
k
k
k 个数的总方案数,可得
f
(
n
,
k
)
=
C
n
−
k
+
1
k
f(n,k)=C_{n-k+1}^{k}
f(n,k)=Cn−k+1k。
然后这里利用了官解里所说的 “ 化环 ” 的思想。
如果把整个序列视为一个环(即第一个点和最后一个点不能同时选),那么
G
′
(
n
,
1
,
k
)
=
G
′
(
n
,
2
,
k
)
=
⋯
=
G
′
(
n
,
n
,
k
)
G'(n,1,k)=G'(n,2,k)=\cdots=G'(n,n,k)
G′(n,1,k)=G′(n,2,k)=⋯=G′(n,n,k),不妨令此时的
G
′
(
n
,
1
,
k
)
=
G
′
(
n
,
2
,
k
)
=
⋯
=
G
′
(
n
,
n
,
k
)
=
F
(
n
,
k
)
G'(n,1,k)=G'(n,2,k)=\cdots=G'(n,n,k)~=~F(n,k)
G′(n,1,k)=G′(n,2,k)=⋯=G′(n,n,k) = F(n,k),则通过一番组合推导,可以发现
F
(
n
,
k
)
=
{
n
<
3
:
[
k
=
=
1
]
n
≥
3
:
f
(
n
−
3
,
k
−
1
)
F(n,k)=\bigg\lbrace{\begin{matrix}n<3:~~[k==1]~~~~~~~~~\\ n\geq3:f(n-3,k-1) \end{matrix}}
F(n,k)={n<3: [k==1] n≥3:f(n−3,k−1)
如果不是个环,那就多了一种情况:第一个点和最后一个点同时选,我们把它加上去就行了。选了第一个点和最后一个点后,相当于中间的长度为
n
−
4
n-4
n−4 的子区间又构成了一个子问题,因此
G
(
n
,
i
,
k
)
G(n,i,k)
G(n,i,k) 有这样的递推公式:
G
(
n
,
i
,
k
)
=
{
i
≤
0
:
0
i
=
1
:
F
(
n
,
k
)
+
f
(
n
−
4
,
k
−
2
)
i
>
1
:
F
(
n
,
k
)
+
G
(
n
−
4
,
i
−
2
,
k
−
2
)
i
>
⌈
n
2
⌉
:
G
(
n
,
n
−
i
+
1
,
k
)
G(n,i,k)=\begin{cases} i\leq0: & 0\\ i=1: & F(n,k)+f(n-4,k-2)\\ i>1: & F(n,k)+G(n-4,i-2,k-2)\\ i>\lceil\frac{n}{2}\rceil: & G(n,n-i+1,k) \end{cases}
G(n,i,k)=⎩⎪⎪⎪⎨⎪⎪⎪⎧i≤0:i=1:i>1:i>⌈2n⌉:0F(n,k)+f(n−4,k−2)F(n,k)+G(n−4,i−2,k−2)G(n,n−i+1,k)
我们将一般情况(
i
>
1
i>1
i>1)展开,可以得到:
G
(
n
,
i
,
k
)
=
F
(
n
,
k
)
+
F
(
n
−
4
,
k
−
2
)
+
F
(
n
−
8
,
k
−
4
)
+
⋯
G(n,i,k)=F(n,k)+F(n-4,k-2)+F(n-8,k-4)+\cdots
G(n,i,k)=F(n,k)+F(n−4,k−2)+F(n−8,k−4)+⋯
不难发现对于不同的
i
i
i ,前面部分都是一样的,
i
i
i 只决定式子长度以及最后一项!
那么我们就可以从左到右遍历
i
i
i 的时候把
G
(
n
,
i
,
k
)
G(n,i,k)
G(n,i,k) 衔接着求,只求前一半。每次到新的
i
i
i 最多会增加或减少一两项。由于递推式中每次
i
i
i 会减少 2,且
i
=
1
i=1
i=1 属于特殊情况,所以要分奇偶性讨论。
具体实现有点细节,但是只求前一半,再考虑考虑边界应该就没问题了。
时间复杂度
O
(
n
)
O(n)
O(n)。
CODE
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 1000005
#define DB double
#define LL long long
#define ENDL putchar('\n')
#define lowbit(x) ((-x) & (x))
#define INF 0x3f3f3f3f
LL read() {
LL f=1,x=0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
const int MOD = 998244353;
int n,m,i,j,s,o,k;
int a[MAXN];
int fac[MAXN],inv[MAXN],invf[MAXN];
inline int qkpow(int a,int b) {
int res = 1;
while(b > 0) {
if(b & 1) res = res *1ll* a % MOD;
a = a *1ll* a % MOD; b >>= 1;
}return res;
}
inline int C(int n,int m) {
if(m < 0 || m > n) return 0;
return 1ll*fac[n] * invf[n-m] % MOD *invf[m] % MOD;
}
inline int f_(int n,int k) {return C(n-k+1,k);}
inline int F(int n,int k) {
if(n <= 3) {
if(k == 1) return 1;
else return 0;
}
else return f_(n-3,k-1);
}
int tm[MAXN];
int main() {
n = read();k = read();int D = read();
int ans = 0;
fac[0] = fac[1] = inv[0] = inv[1] = invf[1] = invf[0] = 1;
for(int i = 2;i <= n;i ++) {
fac[i] = fac[i-1] *1ll* i % MOD;
inv[i] = (MOD-inv[MOD%i]) *1ll* (MOD/i) % MOD;
invf[i] = invf[i-1] *1ll* inv[i] % MOD;
}
for(int i = 1;i <= n;i ++) {
a[i] = read(); tm[i] = -1;
}
int ans0 = 0,ans1 = f_(n,k),ad1 = 0,ad2 = 0;
for(int i = 1;i <= n;i ++) {
if(i & 1) {
(ans1 += MOD-f_(n-4*ad1,k-2*ad1)) %= MOD;
(ans1 += F(n-4*ad1,k-2*ad1)) %= MOD;
ad1 ++;
(ans1 += f_(n-4*ad1,k-2*ad1)) %= MOD;
if(tm[i] >= 0) ans1 = tm[i];
else tm[i] = tm[n-i+1] = ans1;
(ans += ans1 *1ll* a[i] % MOD) %= MOD;
}
else {
(ans0 += F(n-4*ad2,k-2*ad2)) %= MOD; ad2 ++;
if(tm[i] >= 0) ans0 = tm[i];
else tm[i] = tm[n-i+1] = ans0;
(ans += ans0 *1ll* a[i] % MOD) %= MOD;
}
}
printf("%d\n",ans);
return 0;
}
ARC120F Wine Thief (组合数学)的更多相关文章
- 17995 Stupid thief 组合数学
17995 Stupid thief 时间限制:1000MS 内存限制:65535K提交次数:0 通过次数:0 题型: 编程题 语言: 不限定 Description A stupid thie ...
- 记录在linux下的wine生活
记录在linux下的windows生活 本篇内容涉及QQ.微信.Office的安装配置 QQ: 到deepin下载轻聊版. 如果安装了crossover,那么将其中opt/cxoffice/suppo ...
- linux Mint wine安装qq,桌面快捷键配置
在桌面新建qq.desktop文件,添加以下内容 #!/usr/bin/env xdg-open[Desktop Entry]Comment=QQTerminal=falseName=QQExec=w ...
- Wine——在Linux上运行Windows软件
官网:https://www.winehq.org/ 参考: wikipedia 教你使用Wine在Linux上运行Windows软件 如何安装和使用Wine,以便在Linux上运行Windows应用 ...
- codeforces 632+ E. Thief in a Shop
E. Thief in a Shop time limit per test 5 seconds memory limit per test 512 megabytes input standard ...
- linux安装wine
1.添加PPA sudo add-apt-repository ppa:ubuntu-wine/ppa 2.更新列表 sudo apt-get update 3.安装Wine sudo apt-get ...
- Codeforces632E Thief in a Shop(NTT + 快速幂)
题目 Source http://codeforces.com/contest/632/problem/E Description A thief made his way to a shop. As ...
- CentOS 安装 Wine
1. 下载安装包 Wine的中文官网可以下载到最新稳定和开发版本的Wine安装包,根据不同需求可以自行下载 2. 解压安装包,编译前检查 根据不同的平台选择不同的编译选项: For 32-Bit Sy ...
- wine
sudo dpkg --add-architecture i386 sudo add-apt-repository ppa:wine/wine-buildssudo apt-get update su ...
随机推荐
- vscode远程调试c++
0.背景 最近在学习linux webserver开发,需要在linux下调试自己的C/C++代码,但是linux下不像在windows下,直接Visio Studio或者其它集成开发环境那么方便,现 ...
- Quartus II 13.0 sp1的官方下载页面
今天为了下个ModelSim跑到网上去找下载资源,清一色的百度网盘,下载速度60k/s,简直有病,于是跑到Intel官网上把连接挖出来了,供各位直接下载 实测使用IDM多线程下载速度可以轻松上到数MB ...
- React + Typescript领域初学者的常见问题和技巧
React + Typescript领域初学者的常见问题和技巧 创建一个联合类型的常量 Key const NAME = { HOGE: "hoge", FUGA: "f ...
- 智慧机房3D可视化技术解决方案
随着夏季气温越来越高,机房内大量设备同步工作时,难免使机房内温度飙升. 机房温度每升高10℃,计算机的可靠性就下降25% 磁盘磁带也会因热涨效应造成记录错误 计算机的时钟主频在温度过高都会降低 UPS ...
- 我大抵是卷上瘾了,横竖睡不着!竟让一个Bug,搞我两次!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言:一个Bug 没想到一个Bug,竟然搞我两次! 我大抵是卷上瘾了,横竖都睡不着,坐起来 ...
- UiPath视频教程
UiPath机器人企业框架简介https://www.bilibili.com/video/BV1SK411L7u9 UiPath借助第三方Pdf软件工作https://www.bilibili.co ...
- Python爬取全球是最大的电影数据库网站IMDb数据
在使用 Python 开发爬虫的过程中,requests 和 BeautifulSoup4(别名bs4) 应用的比较广泛,requests主要用于模拟浏览器的客户端请求,以获取服务器端响应,接收到的响 ...
- AI 绘画极简教程
昨天在朋友圈发了几张我用AI绘画工具Disco Diffusion画的画 既然有同学问,就写个极简教程吧,画个图是足够了,想要深入了解还是自行百度吧,可以找到更详细的教程. 第 0 步:学会上网,注册 ...
- gnet: 一个轻量级且高性能的 Go 网络框架 使用笔记
一个偶然的机会接触到了golang,被它的高并发传说所吸引,就开始学这门语言,越学感觉越有意思^_^ 注册了博客园这么多年,第一次写东西,年纪大了,脑子不好使了,就得写下来,记下来,为了自己以后查阅, ...
- 数据结构-二叉树(Binary Tree)
1.二叉树(Binary Tree) 是n(n>=0)个结点的有限集合,该集合或者为空集(空二叉树),或者由一个根节点和两棵互不相交的,分别称为根节点的左子树和右子树的二叉树组成. 2.特数二 ...