Description

题库链接

给你 \(n\) 块白木板,\(k\) 块红木板,分别有各自的长度 \(h_i\)。让你用这些木板组成一段围栏,要满足:

  1. 只用一块红木板,且所有白木板的长度均严格小于红木板长度;
  2. 红木板左边的白木板长度严格单调递增;
  3. 红木板右边的白木板长度严格单调递减

现在给出 \(q\) 组询问,问周长为 \(x_i\) 的围栏有多少种。

\(1\leq n,h_i,q\leq 3\cdot 10^5,4\leq x_i\leq 12\cdot 10^5,1\leq k\leq 5\)

Solution

如果我们选的红木板长度为 \(L\),并且这段围栏由 \(m\) 块板子构成,显然周长为 \(2\times (L+m)\)。

那么问题就转化为了,求用 \(m-1\) 块长度 \(<L\) 的白木板形成两段长度严格单调递增序列的方案数。

因为木板长度是离散的,我们可以考虑每种长度的木板的放法。

我们把所有长度 \(<L\) 的白木板取出。若某种长度的木板只有一块。那么显然,这块木板可以放在红木板的左边或右边(即任意一个序列中)。

对于某种长度有两块以上的时候,我们可以把他放在左边、右边或者两边都放。并且我们最多只会用 \(2\) 块这样的木板,所以多余的可以除去。

假设第一种情况(该长度的木板只有一块)下的木板个数为 \(sa\)。显然用这 \(sa\) 块木板构成两段序列总长度为 \(i\) 的方案数 \(a_i={sa \choose i}\times 2^i\)。

假设第二种情况下的木板个数为 \(sb\)(除去多余的木板)。用这 \(sb\) 块木板构成两段序列总长度为 \(i\) 的的方案数 \(b_i={sb \choose i}\)。

记两种情况长度总和为 \(i\) 的方案数为 \(c_i\),那么容易发现我们要求的就是

\[
c_{m-1}=\sum_{i=0}^{m-1}a_ib_{m-1-i}
\]

这是一个卷积式,那么我们设

\[
\begin{aligned}
A(x)&=\sum_i a_i x^i\\
B(x)&=\sum_i b_i x^i\\
C(x)&=A(x)\otimes B(x)\\
&=\sum_i c_i x^i
\end{aligned}
\]

那么我们就可以用 \(\text{NTT}\) 来求出选该红木板时,对应选不同白木板个数的方案数了。

因此我们可以枚举每个红木板,做一次 \(\text{NTT}\) 累计到答案中,\(O(1)\) 回答询问。

总复杂度 \(O(k\times n\log n +q)\)。

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 12e5+5, yzh = 998244353; int n, k, q, cnt[N], x, ans[N], fac[N], ifac[N];
int A[N], B[N], a, b, L, R[N]; int quick_pow(int a, int b) {
int ans = 1;
while (b) {
if (b&1) ans = 1ll*ans*a%yzh;
b >>= 1, a = 1ll*a*a%yzh;
}
return ans;
}
int C(int n, int m) {return 1ll*fac[n]*ifac[m]%yzh*ifac[n-m]%yzh; }
void NTT(int *A, int o) {
for (int i = 0; i < n; i++) if (i < R[i]) swap(A[i], A[R[i]]);
for (int i = 1; i < n; i <<= 1) {
int gn = quick_pow(3, (yzh-1)/(i<<1)), x, y;
if (o == -1) gn = quick_pow(gn, yzh-2);
for (int j = 0; j < n; j += (i<<1)) {
int g = 1;
for (int k = 0; k < i; k++, g = 1ll*g*gn%yzh) {
x = A[j+k], y = 1ll*g*A[j+k+i]%yzh;
A[j+k] = (x+y)%yzh;
A[j+k+i] = (x-y)%yzh;
}
}
}
}
int main() {
scanf("%d%d", &n, &k);
fac[0] = ifac[0] = ifac[1] = 1;
for (int i = 2; i <= n; i++) ifac[i] = -1ll*yzh/i*ifac[yzh%i]%yzh;
for (int i = 1; i <= n; i++)
fac[i] = 1ll*i*fac[i-1]%yzh,
ifac[i] = 1ll*ifac[i-1]*ifac[i]%yzh;
for (int i = 1; i <= n; i++) scanf("%d", &x), cnt[x]++;
while (k--) {
scanf("%d", &x); a = b = 0;
for (int i = 1; i < x; i++)
if (cnt[i] >= 2) a += 2;
else if (cnt[i] == 1) b++;
memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));
for (int i = 0; i <= a; i++) A[i] = C(a, i);
for (int i = 0; i <= b; i++) B[i] = 1ll*C(b, i)*quick_pow(2, i)%yzh;
a += b; L = 0;
for (n = 1; n <= a; n <<= 1) ++L;
for (int i = 0; i < n; i++) R[i] = (R[i>>1]>>1)|((i&1)<<(L-1));
NTT(A, 1), NTT(B, 1);
for (int i = 0; i < n; i++) A[i] = 1ll*A[i]*B[i]%yzh;
NTT(A, -1);
int inv = quick_pow(n, yzh-2);
for (int i = 0; i <= a; i++) A[i] = 1ll*A[i]*inv%yzh;
for (int i = 0; i <= a; i++)
(ans[(x+1+i)<<1] += A[i]) %= yzh;
}
scanf("%d", &q);
while (q--) scanf("%d", &x), printf("%d\n", (ans[x]+yzh)%yzh);
return 0;
}

[Codeforces 1251F]Red-White Fence的更多相关文章

  1. codeforces 349B Color the Fence 贪心,思维

    1.codeforces 349B    Color the Fence 2.链接:http://codeforces.com/problemset/problem/349/B 3.总结: 刷栅栏.1 ...

  2. Codeforces 484E Sign on Fence(是持久的段树+二分法)

    题目链接:Codeforces 484E Sign on Fence 题目大意:给定给一个序列,每一个位置有一个值,表示高度,如今有若干查询,每次查询l,r,w,表示在区间l,r中, 连续最长长度大于 ...

  3. codeforces 399B. Red and Blue Balls 解题报告

    题目链接:http://codeforces.com/problemset/problem/399/B 题目意思:给出 n 个只由 R 和 B 组成的字符串(由上到下排列,相当于栈),问最多可以操作多 ...

  4. codeforces B. Color the Fence 解题报告

    题目链接:http://codeforces.com/problemset/problem/349/B 题目意思:给定v升的颜料和9个需要花费ad 升的颜料,花费ad 升的颜料意味着得到第d个数字,现 ...

  5. 【贪心】Codeforces 349B.Color the Fence题解

    题目链接:http://codeforces.com/problemset/problem/349/B 题目大意 小明要从9个数字(1,2,--,9)去除一些数字拼接成一个数字,是的这个数字最大. 但 ...

  6. Codeforces 1132C - Painting the Fence - [前缀和优化]

    题目链接:https://codeforces.com/contest/1132/problem/C 题意: 栅栏有 $n$ 个节,有 $q$ 个人可以雇佣来涂栅栏,第 $i$ 个人可以涂第 $l_i ...

  7. Codeforces 349B - Color the Fence

    349B - Color the Fence 贪心 代码: #include<iostream> #include<algorithm> #include<cstdio& ...

  8. Codeforces 448 C. Painting Fence

    递归.分治. . . C. Painting Fence time limit per test 1 second memory limit per test 512 megabytes input ...

  9. Codeforces D. Color the Fence(贪心)

    题目描述: D. Color the Fence time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

随机推荐

  1. xorm-删除和软删除实例

    删除数据Delete方法,参数为struct的指针并且成为查询条件.注意:当删除时,如果user中包含有bool,float64或者float32类型,有可能会使删除失败 package main i ...

  2. linux tomcat开机自启/nginx开机自启

    修改/etc/rc.d/rc.local文件,修改完成后需执行以下指令才能正常自启动 chmod +x /etc/rc.d/rc.local #!/bin/bash # THIS FILE IS AD ...

  3. Java核心技术梳理-IO

    一.引言 IO(输入/输出),输入是指允许程序读取外部数据(包括来自磁盘.光盘等存储设备的数据).用户输入数据.输出是指允许程序记录运行状态,将程序数据输出到磁盘.光盘等存储设备中. IO的主要内容包 ...

  4. 论文笔记: Deep Learning based Recommender System: A Survey and New Perspectives

    (聊两句,突然记起来以前一个学长说的看论文要能够把论文的亮点挖掘出来,合理的进行概括23333) 传统的推荐系统方法获取的user-item关系并不能获取其中非线性以及非平凡的信息,获取非线性以及非平 ...

  5. pandas.to_datetime() 只保留【年-月-日】

    Outline pandas.to_datetime()  生成的日期会默认带有 [2019-07-03 00:00:00]的分钟精度:但有时并不需要这些分钟精度: 去掉分钟精度 可以通过pandas ...

  6. win7下scrapy1.3.2安装

    刚开始学爬虫,网上搜了搜,目前最合适的是选scrapy. 先要安装scrapy. 很多的博客上用的教程都说,scrapy目前对python3支持不是很好.可是不能不学3啊. 先用anaconda最新版 ...

  7. 【开发笔记】- Java中关于HashMap的元素遍历的顺序问题

    今天在使用如下的方式遍历HashMap里面的元素时 for (Entry<String, String> entry : hashMap.entrySet()) { MessageForm ...

  8. Java 之 ServletContext 对象

    ServletContext 对象 一.概念 ServletContext对象:代表整个 web 应用,可以和程序的容器(服务器)来通信. 二.获取 1.通过request 获取 方法: reques ...

  9. Jmeter学习笔记(二十一)——Concurrency Thread Group阶梯式加压测试

    一.先安装jmeter的插件管理工具 1.下载地址:jmeter-plugins.org 点击plugins-manager.jar下载. 2.安装 把下载下来的文件plugins-manager.j ...

  10. FFmpeg参考资料合集(会一直更新)

    让你的软件飞起来:RGB转为YUV 朋友曾经给我推荐了一个有关代码优化的pdf文档<让你的软件飞起来>,看完之后,感受颇深.为了推广其,同时也为了自己加深印象,故将其总结为word 文档. ...