题目分析:

我们可以对每一条边单独计算贡献,这样会发现贡献很好算:

\[ans = \sum_{i=0}^{n-1} w_i \sum_{j=0}^S |j - s_i| \binom{i+j-1}{i-1}\binom{S - j + n - i - 1}{n - i - 1}
\]

这样就可以直接40跑路了

上面假设 \(s_i\) 为 \(a\) 的前缀和。

发现难算的就是第二个求和里面的那些,所以就考虑单独考虑,第一步肯定是化绝对值,化出来就是这个样子的:

\[\sum_{j=0}^S (j - s_i) \binom{i+j-1}{i-1}\binom{S - j + n - i - 1}{n - i - 1} + 2 \times \sum_{j=0}^{s_i} (s_i - j) \binom{i+j-1}{i-1}\binom{S - j + n - i - 1}{n - i - 1}
\]

前后其实本质上是一个东西啦,就选后面的去分析吧。

拆开后就是下面这些:

\[s_i \sum_{j=0}^{s_i}\binom{i+j-1}{i-1}\binom{S - j + n - i - 1}{n - i - 1} - \sum_{j=0}^{s_i} j \times \binom{i+j-1}{i-1}\binom{S - j + n - i - 1}{n - i - 1}
\]

其实这个式子我们是有一种冲动的,就是想把它们化的整齐一点,方便合并同类项,那么关键也就是化一下后面的式子啦。

其实就可以化为:

\[i \times \sum_{j=0}^{s_i} \binom{i+j-1}{i}\binom{S - j + n - i - 1}{n - i - 1}
\]

为了舒服一些,我们设出一个 \(f(n,s,i,k)\),其代表:

\[f(n,s,i,k) = \sum_{j=0}^{k}\binom{i+j-1}{i-1}\binom{s - j + n - i - 1}{n - i - 1}
\]

这样我们就可以很轻松地表示出上面这个式子了,即:

\[\sum_{j=0}^{s_i} \binom{i+j-1}{i}\binom{S - j + n - i - 1}{n - i - 1} = f(n+1,S-1,i-1,s_i+1)
\]

其实就是看看怎么把 \(f\) 那个式子变换成这个式子,剩下就不详细说了,这样我们最后的答案就可以表示为:

\[i \times f(n + 1,S - 1,i+1,S-1) - s_i \times f(n,S,i,S) + 2 \times s_i \times f(n,S,i,s_i) - 2 \times i \times f(n+1,S-1,i+1,s_i-1)
\]

我们可以发现因为 \(i,s_i\) 单调递增,所以如果我们可以快速做到由 \(f(n,s,i,k)\) 得到 \(f(n,s,i+1,k)\) 和 \(f(n,s,i,k+1)\) 就可以用线性的复杂度解决问题

可以根据定义直接得到 \(f(n,s,i,k+1)\),但是剩下的那个就很难弄了。

这个时候就要用的 \(f\) 一个很神仙的组合意义:\(s\) 个相同的小球放到 \(n\) 个不同的盒子里,要求前 \(i\) 个盒子放的小球总数小于等于 \(k\) 的方案数。

这个根据定义是很好理解的,每次就是枚举前 \(i\) 个盒子放多少个然后一个插板法。

这个意义其实换句话来说就是:从左到右第 \(k+1\) 个小球一定放在大于编号 \(i\) 的盒子里。那么此时如果我们枚举第 \(k+1\) 个小球放在哪个盒子里,最后得到的式子就是:

\[f(n,s,i,k) = \sum_{j = i+1}^{n} \binom{j + k - 1}{j-1} \binom{n - j + s - k - 1}{n - j}
\]

这个式子就可以解决 \(i\) 的移动了。

这个式子的具体意义就是:\(k\) 个小球放到前 \(j\) 个盒子里,\(s - k - 1\) 个小球放到剩下的 \(n - j + 1\) 个盒子里,这里主要是要注意第 \(j\) 个盒子我们钦定放了第 \(k+1\) 个球,但不一定仅仅是放了这一个。

代码:

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e6+5;
const int MOD = 998244353;
int fac[N],inv[N],sum[N],w[N];
inline int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int mod(int x){
if(x < 0) return (x%MOD + MOD)%MOD;
else return x % MOD;
}
int binom(int n,int m){
if(n < m || n < 0 || m < 0) return 0;
return mod(fac[n] * mod(inv[m] * inv[n - m]));
}
struct fun{
int n,s,i,k,res;
void init(int _n,int _s,int _i,int _k){
n = _n,s = _s,i = _i,k = _k;res = 0;
for(int j=0; j<=k; j++){
res = mod(res + binom(i + j - 1,i - 1) * binom(s - j + n - i - 1,n - i - 1));
}
}
void movei(int x){
if(x <= i) return;
for(int j=i+1; j<=x; j++){
res = mod(res - binom(j + k - 1,j - 1) * binom(s - k - 1 + n - j,n - j));
}
i = x;
}
void movek(int x){
if(x <= k) return;
for(int j=k+1; j<=x; j++){
res = mod(res + binom(i + j - 1,i - 1) * binom(s - j + n - i - 1,n - i - 1));
}
k = x;
}
}f1,f2,f3,f4;
int power(int a,int b){
int res = 1;
while(b){
if(b & 1) res = mod(res * a);
a = mod(a * a);
b >>= 1;
}
return res;
}
void pre_work(int n){
fac[0] = 1;
for(int i=1; i<=n; i++) fac[i] = mod(fac[i-1] * i);
inv[n] = power(fac[n],MOD-2);
for(int i=n-1; i>=0; i--) inv[i] = mod(inv[i+1] * (i+1));
}
signed main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
pre_work(3000000);
int T = read();
while(T--){
int n = read();
for(int i=1; i<=n; i++){
int a = read();
sum[i] = sum[i-1] + a;
}
for(int i=1; i<n; i++) w[i] = read();
int ans = 0,S = sum[n];
f1.init(n+1,S-1,1,S-1);f2.init(n,S,1,S); //只要保证单调增,初值都没啥问题的
f3.init(n,S,1,0);f4.init(n+1,S-1,1,-1);
for(int i=1; i<n; i++){
// printf("%lld %lld %lld %lld\n",f1.res,f2.res,f3.res,f4.res);
int tmp = 0;
f1.movei(i+1);f2.movei(i);f3.movei(i);f3.movek(sum[i]);
f4.movei(i+1);f4.movek(sum[i] - 1);
tmp = mod(tmp + i * f1.res);
tmp = mod(tmp - sum[i] * f2.res);
tmp = mod(tmp + 2 * sum[i] * f3.res);
tmp = mod(tmp - 2 * i * f4.res);
ans = mod(ans + w[i] * tmp);
}
printf("%lld\n",ans);
}
return 0;
}

也可能是我的取模过于离谱,这个题竟然有点卡常。

【题解】[LNOI2022] 盒的更多相关文章

  1. [LNOI2022]盒

    \(LNOI2022\)盒 由于是加的形式,那么可以套路的拆贡献,枚举每条边的贡献就好了 \(40pts\) //比较显然的事情 //首先确定了一个B数组之后 //最小的移动应该是 //设左右两侧比原 ...

  2. 题解 [BZOJ4368][IOI2015]boxes纪念品盒

    题面 解析 可以发现,发纪念品有三种方式: 从左边走再原路返回. 从右边走再原路返回. 走一圈. 注意到,第三种走法最多只会走一次, 因为如果走了多次,那发放的物品数量就会>=\(2k\), 那 ...

  3. 二模Day2题解

    小明搬家 题目描述 小明要搬家了,大家都来帮忙. 小明现在住在第N楼,总共K个人要把X个大箱子搬上N楼. 最开始X个箱子都在1楼,但是经过一段混乱的搬运已经乱掉了.最后大家发现这样混乱地搬运过程效率太 ...

  4. 2018.11.26 QLU新生赛部分题解

    问题 L: 寄蒜几盒? 题目描述 现在有一个圆圈,圆圈上有若干个点,请判断能否在若干个点中选择三个点两两相连组成一个等边三角形? 这若干个点在圆圈上按顺时针顺序分布. 如果可以的话输出"Ye ...

  5. openjudge666:放苹果—题解

    (测试这里的markdown,同时也有纪念意义吧--第一次写的题解) 当时刚学递推的时候做的一道题 oj上的666题 666:放苹果 总时间限制: 1000ms 内存限制: 65536kB 描述 把M ...

  6. 【KMP】洛谷P2375 [NOI2014]动物园 题解

        一开始的方向应该对了,但是没有想到合理的优化还是没写出来…… 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己 ...

  7. 洛谷 题解 P1287 【盒子与球】

    题解:P1287 盒子与球 不了解的:stirling数(斯特林数) - 百度百科 分析如下: 设有n个不同的球,分别用b1,b2,--bn表示.从中取出一个球bn,bn的放法有以下两种: 1) bn ...

  8. IOI2015 boxes纪念品盒

    BZOJ 4368: [IOI2015]boxes纪念品盒 BZOJ传送门 Description IOI2015开幕式正在进行最后一个环节.按计划在开幕式期间,每个代表队都将收到由主办方发放的一个装 ...

  9. [bzoj4368][IOI2015]boxes纪念品盒_动态规划_单调队列_贪心

    bzoj4368 IOI2015 boxes纪念品盒 题目链接:https://lydsy.com/JudgeOnline/problem.php?id=4368 数据范围:略. 题解: 如果在一个最 ...

  10. css_02之盒模型、渐变

    1.框模型:盒模型,①对象实际宽度=左右外边距+左右边框+左右内边距 + width:②对象实际高度=上下外边距+上下边框+上下内边距 + height: 2.外边距:margin:取值:①top(上 ...

随机推荐

  1. Nacos基本学习

    一.注册中心 1.启动 1.下载nacos 在Nacos的GitHub页面,提供有下载链接,可以下载编译好的Nacos服务端或者源代码: GitHub主页:https://github.com/ali ...

  2. 使用 Cravatar 解决 Gravatar 头像无法访问的问题

    Gravatar全球通用头像服务 1.基本介绍 Gravatar,即全球公认的头像,是一项免费的头像服务,适用于网站所有者,开发人员以及任何想要轻松且经过验证的在线身份的人.它被内置在每个WordPr ...

  3. 嵌入式-C语言基础:指针偏移打印数组

    在C语言中,数组名代表数组中首元素的地址,所以,下面两句获取数组的首地址是等价的: #include<stdio.h> int main() { int a[5]={1,2,3,4,5}; ...

  4. 为什么Linux需要虚拟内存 [转载好文]

    操作系统中的 CPU 和主内存(Main memory)都是稀缺资源,所有运行在当前操作系统的进程会共享系统中的 CPU 和内存资源,操作系统会使用 CPU 调度器分配 CPU 时间1并引入虚拟内存系 ...

  5. Vue使用Element表单校验错误Cannot read property ‘validate’ of undefined

    在做注册用户的页面使用表单校验一直提示Cannot read property 'validate' of undefined错误,其实这个错误的提示根据有多种情况,比较常见的就是 ref 的名字不一 ...

  6. redux原理分享

    概述 一个状态管理工具 Store:保存数据的地方,你可以把它看成一个容器,整个应用只能有一个 Store. State:包含所有数据,如果想得到某个时点的数据,就要对 Store 生成快照,这种时点 ...

  7. 【每日一题】【遍历orSet】2022年2月1日-NC66 两个链表的第一个公共结点

    描述输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空.(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的) 输入描述:输入分为是3段,第 ...

  8. Redis分布式锁应用

    Redis锁的使用 起因:分布式环境下需对并发进行逻辑一致性控制 架构:springboot2.Redis IDEA实操 先新建RedisLock组件 注:释放锁使用lua脚本保持原子性 @Compo ...

  9. python基础语法&数据类型&运算符

    1.标识符 # -*- coding:utf-8 -*- # @Time :2021/1/16 10:28 # @Author :QAbujiaban # @Email :wbxztoo@163.co ...

  10. 大角度非迭代的空间坐标旋转C#实现

    1. 绪论 在前面文章中提到空间直角坐标系相互转换,测绘坐标转换时,一般涉及到的情况是:两个直角坐标系的小角度转换.这个就是我们经常在测绘数据处理中,WGS-84坐标系.54北京坐标系.80西安坐标系 ...