联合省选 2024 比赛记录
联合省选 2024 比赛记录
Day 1
luogu P10217 [省选联考 2024] 季风
生活在二维平面的小 X 准备拜访小 Y,但由于气候的变化,平面上刮起了季风。小 X 想知道季风的影响下,TA 至少要多少天能够到达小 Y 的家,但小 X 也是第一次遇见这种怪事,所以请精通算法的你来帮忙。
给定 \(n,k,x,y\) 和 \(2n\) 个整数 \(x_0,y_0,x_1,y_1,\dots,x_{n-1},y_{n-1}\)。
找到最小的非负整数 \(m\),使得存在 \(2m\) 个实数 \(x_0',y_0',x_1',y_1',\dots,x_{m-1}',y_{m-1}'\) 满足以下条件,或报告不存在这样的 \(m\):
\(•\) \(\sum \limits_{i=0}^{m-1} (x_i'+x_{i \bmod n})=x\);
\(•\) \(\sum \limits_{i=0}^{m-1} (y_i'+y_{i \bmod n})=y\);
\(•\) \(\forall 0\leq i\leq m-1,|x_i'|+|y_i'|\leq k\)。
特别地,\(m=0\) 时,认为 \(\sum \limits_{i=0}^{m-1} (x_i'+x_{i \bmod n})\) 和 \(\sum \limits_{i=0}^{m-1} (y_i'+y_{i \bmod n})\) 均为 \(0\)。
设 \(\sum n\) 为单个测试点内所有测试数据 \(n\) 的和。对于所有测试数据:\(1\leq T\leq 5\times 10^4\),\(1\leq n\leq 10^5\),\(1\leq \sum n \leq 10^6\),\(0\leq |x|,|y|,|x_i|,|y_i|,k\leq 10^8\)。
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
#define N 1000010
const int inf=1e15;
const int INF=1e18;
int T,n,k,X,Y,x[N],y[N];
int l[N],r[N],sum[N];
int read ()
{
int k=1,s=0;char ch=getchar ();
while (!isdigit (ch)) {if (ch=='-') k=-1;ch=getchar ();}
while (isdigit (ch)) {s=s*10+ch-'0';ch=getchar ();}
return k*s;
}
void Solve (int optX,int optY)
{
int lim=optX*X+optY*Y;
for (int i=1;i<=n;i++)
sum[i]=sum[i-1]+optX*x[i]+optY*y[i]+k;
if (sum[n]==0)
{
for (int i=1;i<=n;i++)
if (sum[i]<lim) r[i]=-1;
return;
}
for (int i=1;i<=n;i++)
if (sum[n]<0)
{
if (sum[i]<lim) r[i]=-1;
else r[i]=min (r[i],(lim-sum[i])/sum[n]);
}
else if (sum[i]<lim)
l[i]=max (l[i],(lim-sum[i])%sum[n]?(lim-sum[i])/sum[n]+1:(lim-sum[i])/sum[n]);
}
void Init ()
{
n=read (),k=read (),X=read (),Y=read ();
for (int i=1;i<=n;i++)
{
x[i]=read (),y[i]=read ();
l[i]=0,r[i]=inf;
}
}
void Work ()
{
if (X==0 && Y==0)
{
printf ("0\n");
return;
}
Solve (1,1);
Solve (1,-1);
Solve (-1,1);
Solve (-1,-1);
int ans=INF;
for (int i=1;i<=n;i++)
if (l[i]<=r[i]) ans=min (ans,l[i]*n+i);
if (ans==INF) printf ("-1\n");
else printf ("%lld\n",ans);
}
signed main ()
{
T=read ();
while (T--)
{
Init ();
Work ();
}
return 0;
}
luogu P10218 [省选联考 2024] 魔法手杖
C 城是一座魔力之都,以最高的魔法师水平闻名。对于一名魔法师而言,最重要的固然是魔法手杖和镶嵌在手杖上的魔法水晶。
每个魔法手杖和魔法水晶都可以用魔力值来衡量其能力大小,一个魔法手杖的魔力值是镶嵌在其上的所有魔法水晶中魔力值的最小值。
小 \(\omega\) 是 C 城的一名见习魔法师,他想加强他的魔法手杖。在加强之前,小 \(\omega\) 的魔法手杖镶嵌着 \(n\) 颗魔法水晶,它们的魔力值分别为 \(a_1,a_2,\dots,a_n\)。
小 \(\omega\) 准备使用一次强力的秘术来加强他的手杖。这一次秘术中,他可以任意选择 \(x\),然后将所有魔法水晶的魔力值由 \(a_i\) 变为 \((a_i \oplus x)\),其中 \(\oplus\) 表示按位异或。由于小 \(\omega\) 能力有限,\(a_1,a_2,\dots,a_n\) 和 \(x\) 都是 \([0,2^k-1]\) 中的整数。
小 \(\omega\) 还发现这个秘术可以定向加强。具体地,他可以花费 \(b_i\) 的体力值对第 \(i\) 个魔法水晶进行定向加强,将原本应变为 \((a_i \oplus x)\) 的魔力值变为 \((a_i+x)\)。小 \(\omega\) 能力有限,因此他定向加强所花费的体力值总和不能超过 \(m\),且每个水晶只能被定向加强至多一次。
小 \(\omega\) 想知道他在加强魔法手杖后,魔法手杖的魔力值最大能为多少,但他并不会算,所以请你来帮他计算。
形式化的: 给定 \(a_1,a_2,\dots,a_n\) 以及 \(b_1,b_2,\dots,b_n\),满足 \(a_i \in [0,2^k-1]\) 以及 \(b_i\geq 0\),你需要给出 \(S \subseteq \{1,2,\dots,n\}\) 以及 \(x \in [0,2^k-1]\) 满足以下条件:
\(•\) \(\sum \limits_{i\in S} b_i\leq m\);
\(•\) 满足以上条件的前提下,最大化 \(val(S,x)=\min(\min \limits_{i \in S}(a_i+x),\min \limits_{i \in U \backslash S}(a_i \oplus x))\) 的值。
你只需要给出最大的 \(val(S,x)\) 的值即可。
设 \(\sum n\) 表示单组测试点各组数据 \(n\) 的和。对于所有测试数据,\(T \geq 1\),\(1 \leq n \leq 10^5\),\(1 \leq \sum n \leq 5\times 10^5\),\(0 \leq m \leq 10^9\),\(0 \leq k \leq 120\),\(\forall 1 \leq i \leq n, 0 \leq a_i<2^k\),\(\forall 1 \leq i \leq n, 0 \leq b_i \leq 10^9\)。
零
一个题目中没有的特殊性质:\(\sum\limits_{i=1}^n b_i\leq m\)。
因为 \((x\oplus y)\leq x+y\),所以答案为 \(\min\{a_i\}+x\),\(x\) 取 \(2^k-1\) 即可。
一
特殊性质 \(\text{A}\):\(m=0\);\(\forall 1 \leq i\leq n, b_i\geq 1\)。
即 \(S=\varnothing\),我们需要找到一个 \(x\) 使得 \(ans=\min\limits_{i=1}^n\{a_i\oplus x\}\) 最大,显然 \(ans\) 有二分性,这个后面可能用到。
在 Trie 树上考虑 \(ans\) 和 \(x\) 的值,从高到低考虑 \(ans\) 和 \(x\) 的每一个二进制位上的取值,设当前考虑到第 \(d\) 位,且对应到 Trie 树中的节点为 \(u\)。分两种情况讨论:
-
\(ans\) 的第 \(d\) 位为 \(1\),如果 \(x\) 的第 \(d\) 位为 \(1\),那么 \(u\) 的右子树存在魔法手杖一定不合法;如果 \(x\) 的第 \(d\) 位为 \(0\),那么左子树存在魔法手杖一定不合法。因此 \(ans\) 的第 \(d\) 位为 \(1\) 当且仅当 \(u\) 的左子树或右子树为空。
-
\(ans\) 的第 \(d\) 位为 \(0\),如果 \(x\) 的第 \(d\) 位为 \(1\),那么左子树内的所有魔法手杖一定都合法,只需要考虑右子树内的答案;如果 \(x\) 的第 \(d\) 位为 \(0\),那么右子树内的所有魔法手杖一定都合法,只需要考虑左子树内的答案。
这样可以得到一个特殊性质 \(\text{A}\) 的 \(\mathcal{O}(nk)\) 的做法。
二
特殊性质 \(\text{B}\):\(m=1\);\(\forall 1 \leq i\leq n, b_i \in \{1,2\}\),且至多只有一个 \(i\) 满足 \(b_i=1\);
特殊性质 \(\text{C}\):\(m=1\);\(\forall 1 \leq i\leq n, b_i \in \{1,2\}\)。
这个特殊性质看似弱化了问题,实际上增加了一个条件 \(|S|=1\)。不如直接思考正解。正解相当于将做法 零 和做法 一 拼起来。考虑从正解与前面两个做法的相同和不同之处出发。
设答案为 \(ans\),则 \(val(S,x)\) 需要满足
-
\(\sum\limits_{i\in S} b_i\leq m\);
-
\(\forall i\in U\backslash S\),\((a_i\oplus x)\geq ans\);
-
\(\min\limits_{i\in S}\{a_i\}+x\geq ans\)。
第二个条件与特殊性质 \(\text{A}\) 无异,第一、三个条件增加了两个需要维护的量 \(\min\limits_{i\in S}\{a_i\}\) 和 \(\sum\limits_{i\in S} b_i\)。
仍然在 Trie 树上考虑 \(ans\) 和 \(x\) 的值。
-
\(ans\) 的第 \(d\) 位为 \(1\),如果 \(x\) 的第 \(d\) 位为 \(1\),那么 \(u\) 的右子树所有魔法手杖都需要加入 \(S\);如果 \(x\) 的第 \(d\) 位为 \(0\),那么左子树所有魔法手杖都需要加入 \(S\)。
-
\(ans\) 的第 \(d\) 位为 \(0\),如果 \(x\) 的第 \(d\) 位为 \(1\),那么左子树内的所有魔法手杖一定都合法,只需要考虑右子树内的答案;如果 \(x\) 的第 \(d\) 位为 \(0\),那么右子树内的所有魔法手杖一定都合法,只需要考虑左子树内的答案。
如果 \(ans\) 确定下来,容易计算出 \(\min\limits_{i\in S}\{a_i\}\) 和 \(\sum\limits_{i\in S} b_i\) 判断是否合法,可以得到一个二分 \(ans\) 的 \(\mathcal{O}(nk^2)\) 的做法。
考虑时间复杂度去掉一个 \(k\),即二分转贪心,在 Trie 树上贪心地确定 \(ans\)。一个大致的思路是如果 \(ans\) 该位取 \(1\) 有解则取 \(1\),无解则取 \(0\)。具体地,设当前考虑到 Trie 树上的节点 \(u\),对应到二进制第 \(d\) 位,当前确定下来的需要定向加强的魔法手杖集合为 \(S\)。
\(ans\) 的第 \(d\) 位取 \(1\) 有解当且仅当满足以下两个条件之一:
-
\(x\) 的第 \(d\) 位取 \(1\),设 \(ans\) 二进制位 \(d\) 取 \(1\)、二进制位 \([0,d)\) 全部取 \(0\) 得到 \(ans'\),\(x\) 二进制位 \([0,d]\) 全部取 \(1\) 得到 \(x'\),满足 \(\min_{i\in S} \{a_i\}+x'\geq ans'\),把左子树的所有魔法手杖加入 \(S\) 之后 \(\sum\limits_{i\in S} b_i\leq m\);
-
\(x\) 的第 \(d\) 位取 \(0\),设 \(ans\) 二进制位 \([0,d]\) 全部取 \(0\) 得到 \(ans'\),\(x\) 二进制位 \(d\) 取 \(1\)、二进制位 \([0,d)\) 全部取 \(1\) 得到 \(x'\),满足 \(\min_{i\in S} \{a_i\}+x'\geq ans'\),把右子树的所有魔法手杖加入 \(S\) 之后 \(\sum\limits_{i\in S} b_i\leq m\);
另外若 \(u\) 为空节点,则可以将 \(x\) 的二进制位 \([0,d)\) 全部设为 \(1\)。
这样就得到了一个 \(\mathcal{O}(nk)\) 的做法。
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100010
#define K 125
void read (__int128 &x){
char c; bool f = 0;
while(((c = getchar()) < '0' || c > '9') && c != '-');
if(c == '-'){f = 1; c = getchar();}
x = c - '0';
while((c = getchar()) >= '0' && c <= '9')x = x * 10 + c - '0';
if(f) x = -x;
}
void write(__int128 x){
if(x < 0){putchar('-'); x = -x;}
if(x > 9)write(x / 10);
putchar(x % 10 + '0');
}
int c,T,n,m,k,b[N];
__int128 a[N];
long long sum[N*K];
int idx,Trie[N*K][2];
__int128 minv[N*K],ans;
void DFS (int u,int d,int t,__int128 x,__int128 y,__int128 z)
{
if (d==-1)
{
ans=max (ans,z);
return;
}
if (u==0)
{
ans=max (ans,y+(x|((__int128) 1<<(d+1))-1));
return;
}
int lc=Trie[u][0],rc=Trie[u][1];
bool flag=1;
if (sum[lc]<=t && (x|(((__int128) 1<<d)-1))+min (y,minv[lc])>=(z|((__int128) 1<<d)))
DFS (rc,d-1,t-sum[lc],x,min (y,minv[lc]),z|((__int128) 1<<d)),flag=0;
if (sum[rc]<=t && (x|(((__int128) 1<<(d+1))-1))+min (y,minv[rc])>=(z|((__int128) 1<<d)))
DFS (lc,d-1,t-sum[rc],x|((__int128) 1<<d),min (y,minv[rc]),z|((__int128) 1<<d)),flag=0;
if (flag)
{
DFS (lc,d-1,t,x,y,z);
DFS (rc,d-1,t,x|((__int128) 1<<d),y,z);
}
}
void Init ()
{
scanf ("%d %d %d",&n,&m,&k);
for (int i=1;i<=n;i++)
read (a[i]);
for (int i=1;i<=n;i++)
scanf ("%d",&b[i]);
}
void Work ()
{
minv[0]=(__int128) 1<<k;
idx=1,Trie[idx][0]=Trie[idx][1]=0;
minv[idx]=(__int128) 1<<k,sum[idx]=0;
for (int i=1;i<=n;i++)
{
int u=1;
minv[u]=min (minv[u],a[i]),sum[u]+=b[i];
for (int j=k-1;j>=0;j--)
{
int ch=a[i]>>j&1;
if (!Trie[u][ch])
{
Trie[u][ch]=++idx;
Trie[idx][0]=Trie[idx][1]=0;
minv[idx]=(__int128) 1<<k,sum[idx]=0;
}
u=Trie[u][ch];
minv[u]=min (minv[u],a[i]),sum[u]+=b[i];
}
}
ans=0;
if (sum[1]<=m) ans=minv[1]+((__int128) 1<<k)-1;
else DFS (1,k-1,m,0,(__int128) 1<<k,0);
write (ans),putchar ('\n');
}
signed main ()
{
scanf ("%d %d",&c,&T);
while (T--)
{
Init ();
Work ();
}
return 0;
}
luogu P10219 [省选联考 2024] 虫洞
E 国有 \(n\) 个城市,编号为 \(1\) 至 \(n\)。为了让城市之间的来往更加便利,E 国的交通部想在 \(n\) 个城市间建造一些虫洞。每条虫洞是一条单向的从某个城市到另一个城市的通道。允许通道的起点和终点是同一个城市,也允许两个城市之间有多个虫洞连接。
为了区分虫洞的建造时间,交通部给每一条虫洞一个正整数的编号。
我们称一种虫洞的建造方案是好的,若它满足如下四个条件:
\(•\) 存在一个非负整数 \(d\) 使得每个城市恰好是 \(d\) 条虫洞的起点,也恰好是 \(d\) 条虫洞的终点。
\(•\) 对于每个城市而言,在以它为起点的虫洞的编号中,\(1\) 到 \(d\) 恰好各出现一次。
\(•\) 对于每个城市而言,在以它为终点的虫洞的编号中,\(1\) 到 \(d\) 恰好各出现一次。
\(•\) 任意选取一个城市 \(u\) 和正整数 \(1\le j_1, j_2 \le d\)。设从 \(u\) 出发,先经过一次编号为 \(j_1\) 的虫洞,再经过一次编号为 \(j_2\) 的虫洞,到达城市 \(v_1\)。设从 \(u\) 出发,先经过一次编号为 \(j_2\) 的虫洞,再经过一次编号为 \(j_1\) 的虫洞,到达城市 \(v_2\)。则条件 \(v_1=v_2\) 必定满足。
特别地,不建造任何虫洞的方案也是好的。
现在,建造师已建造了 \(mn\) 条虫洞,且给了它们 \(1\sim m\) 的编号,此时这样的建造方案是好的。他想要新建造 \(kn\) 条虫洞,并给它们 \((m+1)\sim (m+k)\) 的编号。他必须保证这 \((m + k)n\) 条虫洞形成的建造方案仍然是好的。他想知道有多少种新建造 \(kn\) 条虫洞的方法,使得这 \((m + k)n\) 条虫洞形成的建造方案是好的。
由于答案很大,你只需要求出方案数除以 \(998244353\) 的余数。
对于所有测试点,\(1\le n \le 2\cdot 10^3\),\(0 \le m \le 10^3\),\(1 \le k \le 10^{15}\),\(1 \le u,v \le n\),\(1 \le w \le m\)。保证初始建造的 \(mn\) 条虫洞构成一个号的建造方案。
Day 2
luogu P10220 [省选联考 2024] 迷宫守卫
Alice 拥有一座迷宫,这座迷宫可以抽象成一棵拥有 \(2^n\) 个叶节点的满二叉树,总节点数目为 \((2^{n+1} - 1)\),依次编号为 \(1 \sim (2^{n+1} - 1)\)。其中编号为 \(2^n \sim (2^{n+1} - 1)\) 的是叶节点,编号为 \(1 \sim (2^n - 1)\) 的是非叶节点,且非叶节点 \(1 \le u \le (2^n - 1)\) 的左儿子编号为 \(2u\),右儿子编号为 \((2u + 1)\)。
每个非叶节点都有一个石像守卫,初始时,所有石像守卫均在沉睡。唤醒 \(u\) 点的石像守卫需要 \(w_u\) 的魔力值。
每个叶节点都有一个符文,\(v\) 点的符文记作 \(q_v\)。保证 \(q_{2^n}, q_{2^n+1},\cdots, q_{2^{n+1}-1}\) 构成 \(1 \sim 2^n\) 的排列。
探险者初始时持有空序列 \(Q\),从节点 \(1\) 出发,按照如下规则行动:
\(•\) 到达叶节点 \(v\) 时,将 \(v\) 点的符文 \(q_v\) 添加到序列 \(Q\) 的末尾,然后返回父节点。
\(•\) 到达非叶节点 \(u\) 时:
若该点的石像守卫已被唤醒,则只能先前往左儿子,(从左儿子返回后)再前往右儿子,(从右儿子返回后)最后返回父节点。
若该点的石像守卫在沉睡,可以在以下二者中任选其一:先前往左儿子,再前往右儿子,最后返回父节点;先前往右儿子,再前往左儿子,最后返回父节点。
返回节点 \(1\) 时,探险结束。可以证明,探险者一定访问每个叶节点各一次,故此时 \(Q\) 的长度为 \(2^n\)。
探险者 Bob 准备进入迷宫,他希望探险结束时的 \(Q\) 的字典序越小越好,与之相对,Alice 希望 \(Q\) 的字典序越大越好。
在 Bob 出发之前,Alice 可以选择一些魔力值花费之和不超过 \(K\) 的石像守卫,并唤醒它们。Bob 出发时,他能够知道 Alice 唤醒了哪些神像。若双方都采取最优策略,求序列 \(Q\) 的最终取值。
对于两个长度为 \(2^n\) 的序列 \(Q_1,Q_2\),称 \(Q_1\) 字典序小于 \(Q_2\) 当且仅当以下条件成立:
\(•\) \(\exists i \in [1, 2^n]\) 满足以下两个条件:\(\forall 1 \le j < i\),\(Q_{1,j} = Q_{2,j}\);\(Q_{1,i} < Q_{2,i}\)。
设 \(\sum 2^n\) 表示单个测试点中所有测试数据的 \(2^n\) 的和。
对于所有测试数据,保证 \(1\le T \le 100\),\(1\le n \le 16\),\(1 \le \sum 2^n \le 10^5\),\(0\le K \le 10^{12}\),\(\forall 1 \le u \le (2^n-1)\),\(0 \le w_u \le 10^{12}\),\(q_{2^n},q_{2^n+1},\cdots,q_{2^{n+1}-1}\) 构成 \(1\sim 2^n\) 的排列。
零
朴素的思路是枚举唤醒的石像守卫集合 \(S\),然后暴力计算出 Bob 可以得到的最小的字典序 \(Q_{\min}(S)\),然后求 \(\max_{\sum_{i\in S}w_i\leq K}\{Q_{\min}(S)\}\)。
本题的特殊性质 \(\text{A}\)、\(\text{B}\) 不具有参考价值。
一
考虑对 \(\max_{\sum_{i\in S}w_i\leq K}\{Q_{\min}(S)\}\) 进行转化,发现式子过于复杂,没法转化。根据字典序的性质,考虑问题的一部分 \(\max_{\sum_{i\in S}w_i\leq K}\{Q_{\min,1}(S)\}\)。
考虑二分答案 \(t=\max_{\sum_{i\in S}w_i\leq K}\{Q_{\min,1}(S)\}\),设 \(f_{u,i}\) 表示以 \(u\) 为根的子树,第一个遍历到的节点编号 \(\geq i\) 的最小代价。容易得到转移:
二分找到最大的 \(t\) 满足 \(f_{1,t}\leq K\) 即可得到 \(\max_{\sum_{i\in S}w_i\leq K}\{Q_{\min,1}(S)\}\)。
时间复杂度 \(\mathcal{O}(4^n)\),将第二维离散化后时间复杂度 \(\mathcal{O}(n2^n)\)。
二
考虑是否可以将原问题转化为上面的子问题,不难发现只要处理出每个子树内第一个遍历的节点然后再确定每个节点两个儿子的遍历顺序即可得到答案。设 \(\text{Solve}(u,k)\) 表示考虑到节点 \(u\),Alice 还剩下 \(k\) 的魔法值的最小花费。首先二分出最大的 \(t\) 满足 \(f_{u,t}\leq k\),设 \(t\) 所在的叶子节点为 \(v\)。分两种情况讨论:
-
\(v\) 在 \(u\) 的右子树中,那么 Alice 希望 Bob 先遍历右子树再遍历左子树。而 Bob 选择先遍历右子树当且仅当 \(u\) 没有被唤醒且左子树比右子树劣,则依次执行 \(\Delta_1=\text{Solve}(rson_u,k-f_{lson_u,t})\),\(\Delta_2=\text{Solve}(lson_u,k-\Delta_2)\),输出 \(\Delta_1+\Delta_2\)。
-
\(v\) 在 \(u\) 的左子树中,那么 Alice 希望 Bob 先遍历左子树再遍历右子树,分两种情况讨论:其一是 Alice 将该节点唤醒,则依次执行 \(\Delta_1=\text{Solve}(lson_u,k-w_u)\),\(\Delta_2=\text{Solve}(rson_u,k-w_u-\Delta_1)\),输出 \(\Delta_1+\Delta_2\);其二是左子树比右子树优,即依次执行 \(\Delta_1=\text{Solve}(lson_u,k-f_{lson_u,t})\),\(\Delta_2=\text{Solve}(rson_u,k-\Delta_1)\),输出 \(\Delta_1+\Delta_2\)。我们要使字典序最小的同时 \(\Delta_1+\Delta_2\) 最小,考虑如何判断 Alice 是否将该节点唤醒。先使得左子树字典序最小,执行 \(\Delta_1=\text{Solve}(lson_u,k-\min (w_u,f_{lson_u,t}))\),那么当且仅当 \(\Delta_1>k-f_{lson_u,t}\),Alice 才会将该节点唤醒。
时间复杂度 \(\mathcal{O}(n2^n)\)。
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define lc (x<<1)
#define rc (x<<1|1)
#define N 100010
const long long INF=1e16;
int T,n,b[N];
long long m,a[N];
vector <int> vec;
long long read ()
{
long long k=1,s=0;char ch=getchar ();
while (!isdigit (ch)) {if (ch=='-') k=-1;ch=getchar ();}
while (isdigit (ch)) {s=s*10+ch-'0';ch=getchar ();}
return k*s;
}
long long DFS (int x,int k,int lim)
{
if (k==0) return b[x^(1<<n)]<=lim?INF:0;
return DFS (lc,k-1,lim)+min (a[x],DFS (rc,k-1,lim));
}
void Solve (int x,int k,long long &m)
{
if (k==0)
{
vec.emplace_back (b[x^(1<<n)]);
return;
}
int l=1,r=1<<n,p=1;
long long tmp=0;
while (l<=r)
{
int mid=(l+r)>>1;
long long res=DFS (x,k,mid);
if (res<=m)
{
p=mid+1;
tmp=res;
l=mid+1;
}
else r=mid-1;
}
vec.emplace_back (p);
m-=tmp;
int y=x<<k;
while (b[y^(1<<n)]!=p) y++;
for (int i=0;i<k;i++)
{
long long res=DFS (y^1,i,p);
if (y&1) m+=res;
else
{
m+=min (res,a[y>>1]);
if (m<res) m-=a[y>>1];
}
Solve (y^1,i,m);
y>>=1;
}
}
void Init ()
{
n=read (),m=read ();
for (int i=1;i<(1<<n);i++)
a[i]=read ();
for (int i=0;i<(1<<n);i++)
b[i]=read ();
}
void Work ()
{
vec.clear ();
Solve (1,n,m);
for (int i=0;i<vec.size ();i++)
{
int x=vec[i];
printf ("%d ",x);
}
printf ("\n");
}
signed main ()
{
T=read ();
while (T--)
{
Init ();
Work ();
}
return 0;
}
luogu P10221 [省选联考 2024] 重塑时光
小 T 正在研究某段时间中所发生的事件。经观测,有 \(n\) 个编号为 \(1\sim n\) 的事件在这段时间内按顺序依次发生,第 \(i\) 个发生的是事件 \(p_i\)。这个描述事件发生顺序的排列 \(p\) 可称为这段时间的时间线。
突然,邪恶生物小 S 攻击了这条时间线,将这 \(n\) 个事件的发生顺序 \(p\) 变为了在所有长为 \(n\) 的排列中等概率随机选取的一个排列。不仅如此,小 S 还用剪刀把时间线剪断,通过进行 \(k\) 次操作,将排列 \(p\) 分割成了 \((k + 1)\) 段。
具体而言,在小 S 进行第 \(i\) 次操作时,排列 \(p\) 和之前所有插入的剪断点构成了一个长度为 \((n + i - 1)\) 的序列。该序列包括所有相邻元素之间和序列开头、末尾处共有 \((n + i)\) 个插入位置。小 S 将从这些插入位置中等概率随机选取一个位置,插入一个新的剪断点。最后,小 S 从最终被插入的 \(k\) 个剪断点处把序列剪开,将排列 \(p\) 分割成了 \((k + 1)\) 段序列。这 \((k + 1)\) 段序列中可能有空序列。
为了拯救这条即将毁灭的时间线,小 T 决定把这 \((k + 1)\) 段序列按某种顺序重新拼接成一个长度为 \(n\) 的排列,形成一条新的时间线。不过,由于事件之间存在一定的逻辑关系,事件的发生时间之间也存在一些先后顺序要求。经研究,共存在 \(m\) 条先后顺序要求 \((u, v)\),要求事件 \(u\) 的发生时间必须在事件 \(v\) 之前。也就是说,\(u\) 在时间线中的出现位置必须在 \(v\) 之前。
请你设计程序,计算有多大的概率,存在至少一种重新排列这 \((k + 1)\) 段序列,并将其重新拼接为一条新的时间线的方案,能够使所有的 \(m\) 条事件发生时间之间的先后顺序要求都得到满足。
为了避免精度误差,请你输出答案对 \(10^9 +7\) 取模的结果。形式化地,可以证明答案可被表示为一最简分数 \(\dfrac{p}{q}\),请你输出一个 \(x\) 满足 \(0 \le x < 10^9+7\) 且 \(qx \equiv p \pmod {10^9+7}\)。可以证明在题目条件下这样的 \(x\) 总是存在。
对于所有测试数据,\(1 \le n \le 15\),\(0 \le m \le \dfrac{n(n-1)}{2}\),\(0 \le k \le n\),\(1 \le u < v \le n\),保证不存在两对 \((u,v)\) 完全相同。

浙公网安备 33010602011771号