CF1784D Wooden Spoon

news/2024/11/6 9:56:20/

CF1784D Wooden Spoon

题目大意

2 n 2^n 2n个人,进行 n n n轮比赛。比赛的图是一棵完全二叉树。编号小的人一定能赢编号大的人,如果一个人满足:

  • 第一次比赛被打败
  • 打败这个人的人在第二次比赛中被打败
  • 打败上一个人的人在第三次比赛中被打败
  • … \dots
  • 打败上一个人的人在最后一次比赛中被打败

那么这个人就能得到安慰奖。

求对于每个人,有多少种编号的排列来比赛(叶子的排列),使得他能得安慰奖。输出答案模 998244353 998244353 998244353


题解

我们按照题意来构建这棵二叉树,叶子节点就是这个序列,而非叶子节点的权值就是其子树中权值最大的点的权值。假如编号为 k k k的点能拿安慰奖,那么这个点到根的路径上的点的权值一定是单调递减的。

假设这个点到根的权值组成的序列为 a 0 , a 1 … , a n a_0,a_1\dots,a_n a0,a1,an,我们依次来看每个点的贡献。

a i a_i ai的贡献为 C ( 2 n − a i − 2 i − 1 , 2 i − 1 − 1 ) × ( 2 i − 1 ) ! C(2^n-a_i-2^{i-1},2^{i-1}-1)\times (2^{i-1})! C(2nai2i1,2i11)×(2i1)!。也就是说,这个点在没有 k k k的那棵子树中还要放小于他的 2 i − 1 − 1 2^{i-1}-1 2i11个点。因为要小于 a i a_i ai,而且自己是一定要选的,所以要减 a i a_i ai。又因为有 k k k的那一边的点不能选,所以要减 2 i − 1 2^{i-1} 2i1。这棵子树内的点的顺序可以任意排列,所以要乘上 ( 2 i − 1 ) ! (2^{i-1})! (2i1)!

f i , s f_{i,s} fi,s表示第 i i i个数为 s s s时第 i i i个数到第 n n n个数的贡献, g i , s g_{i,s} gi,s表示第 i i i个数小于等于 s s s时第 i i i个数到第 n n n个数的贡献和。那么转移式为

f i , s = g i + 1 , s − 1 × C ( 2 n − s − 2 i − 1 , 2 i − 1 − 1 ) × ( 2 i − 1 ) ! f_{i,s}=g_{i+1,s-1}\times C(2^n-s-2^{i-1},2^{i-1}-1)\times (2^{i-1})! fi,s=gi+1,s1×C(2ns2i1,2i11)×(2i1)!

g i , s = g i , s − 1 + f i , s g_{i,s}=g_{i,s-1}+f_{i,s} gi,s=gi,s1+fi,s

因为 k k k的位置任意,所以最后还要乘上 2 n 2^n 2n。那么编号为 k k k的点的答案就是 g 1 , k − 1 × 2 n g_{1,k-1}\times 2^n g1,k1×2n

时间复杂度为 O ( n × 2 n ) O(n\times 2^n) O(n×2n)

code

#include<bits/stdc++.h>
using namespace std;
const int N=1<<20;
int n;
long long jc[N+5],ny[N+5];
long long f[25][N+5],g[25][N+5];
long long mod=998244353;
long long mi(long long t,long long v){if(!v) return 1;long long re=mi(t,v/2);re=re*re%mod;if(v&1) re=re*t%mod;return re;
}
void init(){jc[0]=1;for(int i=1;i<=N;i++) jc[i]=jc[i-1]*i%mod;ny[N]=mi(jc[N],mod-2);for(int i=N-1;i>=0;i--) ny[i]=ny[i+1]*(i+1)%mod;
}
long long C(int x,int y){if(x<y) return 0;return jc[x]*ny[y]%mod*ny[x-y]%mod; 
}
int main()
{init();scanf("%d",&n);for(int s=1;s<=(1<<n);s++){f[n][s]=C((1<<n)-s-(1<<n-1),(1<<n-1)-1)*jc[1<<n-1]%mod;g[n][s]=(g[n][s-1]+f[n][s])%mod;}for(int i=n-1;i>=1;i--){for(int s=1;s<=(1<<n);s++){f[i][s]=g[i+1][s-1]*C((1<<n)-s-(1<<i-1),(1<<i-1)-1)%mod*jc[1<<i-1]%mod;g[i][s]=(g[i][s-1]+f[i][s])%mod;}}for(int s=1;s<=(1<<n);s++){printf("%lld\n",g[1][s-1]*(1<<n)%mod);}return 0;
}

http://www.ppmy.cn/news/166965.html

相关文章

(38)STM32——NRF24L01无线通信

目录 学习目标 成果展示 介绍 引脚 时序 模式 Enhanced ShockBurstTM收发模式 发送流程 接收流程 SPI指令 寄存器 配置寄存器 自动使能寄存器 RX地址使能寄存器 自动重发寄存器 射频频率设置寄存器 射频设置寄存器 状态寄存器 发送地址设置寄存器 硬件…

【计算机图形学】【代码复现】A-SDF中的数据集制作与数据生成

Follow A-SDF 的Data Generation部分&#xff1a; We follow (1) ANSCH to create URDF for shape2motion dataset (1-2) URDF2OBJ&#xff08;本人认为是1-2之间需要进行的重要的过渡部分&#xff09; (2) Manifold to create watertight meshes (3) and modified mesh_to_sdf…

JVM崩溃产生了 hs_err_pidxxxx.log如何分析

hs_err_pid.log是JVM崩溃时产生的日志文件&#xff0c;包含了JVM崩溃时的线程栈信息、内存信息、CPU信息等&#xff0c;可以帮助我们分析JVM崩溃的原因。下面是分析hs_err_pid.log日志的步骤&#xff1a; 1. 打开hs_err_pid.log文件&#xff0c;查看文件头部的信息&#xff0c…

从零开始Vue3+Element Plus后台管理系统(17)——一键换肤的N种方案

暗黑模式 基于Element Plus和Tailwind CSS灵活的设计&#xff0c;我们很容易在项目中实现暗黑模式&#xff0c;具体可以参考之前的文章《从零开始写一个Vue3Element Plus的后台管理系统(二)——Layout页面布局的实现》 换肤方案 如果需要给用户提供更多主题&#xff0c;更丰…

30天从入门到精通TensorFlow1.x 第三天,tf.variable_scope()共享或重用变量

tf.variable_scope()共享或重用变量 文章目录 一、接前一天二、tf.variable_scope()共享或重用变量1. 背景2. 目的3. tf.variable_scope()基本参数3. tf.variable_scope()作用&#xff08;1&#xff09;.命名空间&#xff08;2&#xff09;.共享变量&#xff08;3&#xff09;.…

医院检验科检验系统(LIS)源码:临检、生化、免疫、微生物

一、检验科检验系统 &#xff08;LIS&#xff09;概述&#xff1a;对接HIS&#xff0c;医生工作站能够方便、及时的查阅患者检验报告。 二、检验科检验系统 &#xff08;LIS&#xff09;主要功能描述&#xff1a; 1.质控品管理&#xff1a; 医院设备质控&#xff08;编码、设…

QT非阻塞挂起

在Qt程序中&#xff0c;有时需要在一定时间内等待某个条件满足&#xff0c;但又不能使用阻塞的方式等待&#xff0c;否则会导致界面卡死&#xff0c;无法响应用户的其他操作。这种情况下可以使用Qt提供的非阻塞挂起方法&#xff0c;如下所示&#xff1a; void nonBlockingPaus…

Backtrader官方中文文档:第二部分Installation安装

本文档参考backtrader官方文档&#xff0c;是官方文档的完整中文翻译&#xff0c;可作为backtrader中文教程、backtrader中文参考手册、backtrader中文开发手册、backtrader入门资料使用。 Backtrader安装 安装须知 Backtrader是自包含的&#xff0c;没有外部依赖(除非你想使…