【NOIP 2024 T2】遗失的赋值
【NOIP 2024 T2】遗失的赋值
NOIP 专栏:NOIP 2024 T2
算法竞赛:
题目链接:洛谷 P11362【NOIP2024】遗失的赋值
题目描述:
小 F 有 nnn 个变量 x1,x2,…,xnx_1, x_2, \ldots , x_nx1,x2,…,xn。每个变量可以取 111 至 vvv 的整数取值。
小 F 在这 nnn 个变量之间添加了 n−1n - 1n−1 条二元限制,其中第 iii(1≤i≤n−11 \leq i \leq n - 11≤i≤n−1)条限制为:若 xi=aix_i = a_ixi=ai,则要求 xi+1=bix_{i+1} = b_ixi+1=bi,且 aia_iai 与 bib_ibi 为 111 到 vvv 之间的整数;当 xi≠aix_i \neq a_ixi=ai 时,第 iii 条限制对 xi+1x_{i+1}xi+1 的值不做任何约束。除此之外,小 F 还添加了 mmm 条一元限制,其中第 jjj(1≤j≤m1 \leq j \leq m1≤j≤m)条限制为:xcj=djx_{c_j} = d_jxcj=dj。
小 F 记住了所有 cjc_jcj 和 djd_jdj 的值,但把所有 aia_iai 和 bib_ibi 的值都忘了。同时小 F 知道:存在给每一个变量赋值的方案同时满足所有这些限制。
现在小 F 想知道,有多少种 ai,bia_i, b_iai,bi(1≤i≤n−11 \leq i \leq n - 11≤i≤n−1)取值的组合,使得能够确保至少存在一种给每个变量 xix_ixi 赋值的方案可以同时满足所有限制。由于方案数可能很大,小 F 只需要你输出方案数对 109+710^9 + 7109+7 取模的结果。
输入格式:
(本题包含多组测试数据)
输入的第一行包含一个整数 TTT,表示测试数据的组数。
接下来包含 TTT 组数据,每组数据的格式如下:
第一行包含三个整数 n,m,vn, m, vn,m,v,分别表示变量个数、一元限制个数和变量的取值上限。
接下来 mmm 行,第 jjj 行包含两个整数 cj,djc_j, d_jcj,dj,描述一个一元限制。
输出格式:
对于每组测试数据输出一行,包含一个整数,表示方案数对 109+710^9 + 7109+7 取模的结果。
数据范围:
- 1≤T≤101 \leq T \leq 101≤T≤10,
- 1≤n≤1091 \leq n \leq 10^91≤n≤109,1≤m≤1051 \leq m \leq 10^51≤m≤105,2≤v≤1092 \leq v \leq 10^92≤v≤109,
- 对于任意的 jjj(1≤j≤m1 \leq j \leq m1≤j≤m),都有 1≤cj≤n1 \leq c_j \leq n1≤cj≤n,1≤dj≤v1 \leq d_j \leq v1≤dj≤v。
目录
- 【NOIP 2024 T2】遗失的赋值
- 题目大意
- 题目分析
- 题目思路
- 题目做法
- 参考代码
- END
- 更新日志
题目大意
对于 nnn 个变量 xi,i∈[1,n]x_i,i\in [1,n]xi,i∈[1,n],其取值范围为 {y∣1≤y≤v,y∈Z}\{y | 1\le y\le v,y\in \mathbb{Z}\}{y∣1≤y≤v,y∈Z},变量的取值要满足 n−1n-1n−1 个二元限制和 mmm 个一元限制,限制如下:
- ai,bi,i∈[1,n−1]a_i,b_i,i\in [1,n-1]ai,bi,i∈[1,n−1] 为二元限制参数,取值范围为 {y∣1≤y≤v,y∈Z}\{y | 1\le y\le v,y\in \mathbb{Z}\}{y∣1≤y≤v,y∈Z},限制为:如果 xi=aix_i=a_ixi=ai 则要求 xi+1=bix_{i+1}=b_ixi+1=bi。
- cj,dj,j∈[1,m]c_j,d_j,j\in [1,m]cj,dj,j∈[1,m] 为一元限制参数,取值范围为 {y∣1≤y≤v,y∈Z}\{y | 1\le y\le v,y\in \mathbb{Z}\}{y∣1≤y≤v,y∈Z},限制为:xcj=djx_{c_j}=d_jxcj=dj。
现在已知 mmm 组一元限制的参数 cj,djc_j,d_jcj,dj,对于参数 ai,bi,i∈[1,n−1]a_i,b_i,i\in [1,n-1]ai,bi,i∈[1,n−1] 取值的组合,使得至少存在一种给每个变量 xix_ixi 赋值的方案满足所有限制,求出组合的方案数,并且对 109+710^9+7109+7 取模。
题目分析
根据题目所述,容易知道:
- 如果一元限制之间有冲突,则方案数为 000,即当 i≠ji\ne ji=j 时,若存在 ci=cjc_i=c_jci=cj,而 di≠djd_i\ne d_jdi=dj,则方案数为 ans=0ans=0ans=0。
- 对于一对连续的变量 xi,xi+1x_i,x_{i+1}xi,xi+1,如果两者均没有一元限制,那么 ai,bia_i,b_iai,bi 的取值组合方案数为 v2v^2v2,进而对于一个长度为 nnn 且没有一元限制的变量 xi,i∈[1,n]x_i,i\in [1,n]xi,i∈[1,n] 序列,由乘法原理可知,参数 ai,bi,i∈[1,n−1]a_i,b_i,i\in [1,n-1]ai,bi,i∈[1,n−1] 满足要求的组合方案数为 ans=v2(n−1)ans=v^{2(n-1)}ans=v2(n−1)。
- 对于一个长度为 nnn 且仅左端点有一元限制的变量 xi,i∈[1,n]x_i,i\in [1,n]xi,i∈[1,n] 序列,其方案数也为 ans=v2(n−1)ans=v^{2(n-1)}ans=v2(n−1),因为左端点有一元限制,就相当于确定左端点变量的值,而二元限制是对于前一个数满足条件则限制后一个数,所以仅左端点存在一元限制并无实际作用意义。
- 对于一个长度为 nnn 且仅右端点有一元限制的变量 xi,i∈[1,n]x_i,i\in [1,n]xi,i∈[1,n] 序列,其方案数也为 ans=v2(n−1)ans=v^{2(n-1)}ans=v2(n−1),与仅左端点存在一元限制情况同理,可以从右向左来确定二元限制,这样就相当于仅左端点存在一元限制。
题目思路
WayofThinking\large \textit{\textbf {Way of Thinking}}Way of Thinking
对于一个长度为 nnn 且仅左右端点有一元限制的变量 xi,x2,x3,⋯,xn−2,xn−1,xnx_i,x_2,x_3,\cdots,x_{n-2},x_{n-1},x_nxi,x2,x3,⋯,xn−2,xn−1,xn 序列,存在 kkk 个二元限制(k=n−1k=n-1k=n−1),设其方案数为 f(k)f(k)f(k)。
- 对于 x1,x2x_1,x_2x1,x2 之间的二元限制 (a1,b1)(a_1,b_1)(a1,b1) 如果使 a1=x1a_1=x_1a1=x1,则要 x2=b2x_2=b_2x2=b2,此时 a1a_1a1
存在一种方案,而 b1b_1b1 有 vvv 种方案,故第一对二元限制 (a1,b1)(a_1,b_1)(a1,b1) 有 vvv 种方案,这时相当于给 x2x_2x2
添加了一元限制,故序列的方案数为 v×f(k−1)v\times f(k-1)v×f(k−1)。 - 如果使 a1≠x1a_1\ne x_1a1=x1,这样 a1a_1a1 存在 v−1v-1v−1 种方案,b1b_1b1 有 vvv 种方案,故第一对二元限制 (a1,b1)(a_1,b_1)(a1,b1) 有 v×(v−1)v\times (v-1)v×(v−1) 种方案,这时对于 i≥2i\ge 2i≥2 的 xix_ixi 序列相当于变成了一个仅右端点存在一元限制的变量序列 x2,x3,⋯,xn−2,xn−1,xnx_2,x_3,\cdots,x_{n-2},x_{n-1},x_nx2,x3,⋯,xn−2,xn−1,xn,对于这个序列方案数有 v2(k−1)v^{2(k-1)}v2(k−1) 种,故这种情况的方案数为 v×(v−1)×v2(k−1)v\times (v-1)\times v^{2(k-1)}v×(v−1)×v2(k−1),即 v2k−v2k−1v^{2k}-v^{2k-1}v2k−v2k−1。
特殊的,对于 kkk 取值的边界,当 k=1k=1k=1 时,f(x)=v×(v−1)+1=v2−v+1f(x)=v\times (v-1)+1=v^2-v+1f(x)=v×(v−1)+1=v2−v+1。
综上所述,f(k)=v2k−v2k−1+v×f(k−1)f(k)=v^{2k}-v^{2k-1}+v\times f(k-1)f(k)=v2k−v2k−1+v×f(k−1)。这样就有了一个方案数的递推式,然而如果递推地求解时间复杂度有些高,那么试一试能否将 f(k)f(k)f(k) 变成一个关于 kkk 的一个函数(vvv 作为常量)。
将 f(k)f(k)f(k) 展开:
f(k)=v2k−v2k−1+v×f(k−1)=v2k−v2k−1+v×(v2x−2−v2x−3+v×f(k−2))=v2k−v2k−1+v2x−1−v2x−2+v2×f(k−2)=v2k−v2x−2+v2×f(k−2)=v2k−v2k−2+v2×(v2x−4−v2x−5+v×f(k−3))=v2k−v2k−2+v2x−2−v2x−3+v3×f(k−3)=v2k−v2x−3+v3×f(k−3)=⋯⋯\begin{align} f(k) & = v^{2k}-v^{2k-1}+v\times f(k-1) \\ & = v^{2k}-v^{2k-1}+v\times (v^{2x-2}-v^{2x-3}+v\times f(k-2)) \\ & = v^{2k}-v^{2k-1}+v^{2x-1}-v^{2x-2}+v^2\times f(k-2) \\ & = v^{2k}-v^{2x-2}+v^2\times f(k-2) \\ & = v^{2k}-v^{2k-2}+v^2\times (v^{2x-4}-v^{2x-5}+v\times f(k-3)) \\ & = v^{2k}-v^{2k-2}+v^{2x-2}-v^{2x-3}+v^3\times f(k-3) \\ & = v^{2k}-v^{2x-3}+v^3\times f(k-3) \\ & = \cdots \hspace{0mm} \cdots \\ \end{align}f(k)=v2k−v2k−1+v×f(k−1)=v2k−v2k−1+v×(v2x−2−v2x−3+v×f(k−2))=v2k−v2k−1+v2x−1−v2x−2+v2×f(k−2)=v2k−v2x−2+v2×f(k−2)=v2k−v2k−2+v2×(v2x−4−v2x−5+v×f(k−3))=v2k−v2k−2+v2x−2−v2x−3+v3×f(k−3)=v2k−v2x−3+v3×f(k−3)=⋯⋯
由 line(4),line(7)line(4),line(7)line(4),line(7) 行可以得出 f(k)f(k)f(k) 与 f(k−t)f(k-t)f(k−t) 的关系:
f(k)=v2k−v2k−t+vt×f(k−t)f(k)=v^{2k}-v^{2k-t}+v^t\times f(k-t)f(k)=v2k−v2k−t+vt×f(k−t)
为消去 ttt,将 t=k−1t=k-1t=k−1 代入得:
f(k)=v2k−v2k−t+vt×f(k−t)=v2k−v2k−(k−1)+vk−1×f(k−(k−1))=v2k−vk+1+vk−1×f(1)=v2k−vk+1+vk−1×(v2−v+1)=v2k−vk+1+vk+1−vk+vk−1=v2k−vk+vk−1\begin{align} f(k) & = v^{2k}-v^{2k-t}+v^t\times f(k-t) \\ & = v^{2k}-v^{2k-(k-1)}+v^{k-1}\times f(k-(k-1)) \\ & = v^{2k}-v^{k+1}+v^{k-1}\times f(1) \\ & = v^{2k}-v^{k+1}+v^{k-1}\times (v^2-v+1) \\ & = v^{2k}-v^{k+1}+v^{k+1}-v^k+v^{k-1} \\ & = v^{2k}-v^k+v^{k-1} \\ \end{align}f(k)=v2k−v2k−t+vt×f(k−t)=v2k−v2k−(k−1)+vk−1×f(k−(k−1))=v2k−vk+1+vk−1×f(1)=v2k−vk+1+vk−1×(v2−v+1)=v2k−vk+1+vk+1−vk+vk−1=v2k−vk+vk−1
故得知:
f(k)=v2k−vk+vk−1f(k)=v^{2k}-v^k+v^{k-1}f(k)=v2k−vk+vk−1
题目做法
SpecificSolution\large \textit{\textbf {Specific Solution}}Specific Solution
对于每组测试数据:
- 读入并存储 mmm 个一元限制,判断一元限制之间是否冲突(若冲突则输出 000 并进行下一轮数据);
- 将一元限制按 ci,i∈[1,m]c_i,i\in [1,m]ci,i∈[1,m] 升序排序并去重,得到 ci,i∈[1,m′]c_i,i\in [1,m']ci,i∈[1,m′];
- 计算变量序列 x[1∼c1]x[1\sim c_1]x[1∼c1] 的方案数 v2(c1−1)v^{2(c_1-1)}v2(c1−1) 和 x[cm′∼n]x[c_{m'}\sim n]x[cm′∼n] 的方案数 v2(n−cm′)v^{2(n-c_{m'})}v2(n−cm′),根据乘法原理将两者相乘得到 ansansans;
- 遍历序列 c[1∼m′]c[1\sim m']c[1∼m′],对于每个 ci,i∈[1,m′−1]c_i,i\in [1,m'-1]ci,i∈[1,m′−1],使 ans=ans×f(ci+1−ci)ans=ans\times f(c_{i+1}-c_i)ans=ans×f(ci+1−ci),得到最终方案数 ansansans。
注意:
- 在公式 f(k)=v2k−vk+vk−1f(k)=v^{2k}-v^k+v^{k-1}f(k)=v2k−vk+vk−1 中存在含有模运算的减法,在取模之前需要加上模数(这很重要)。
- 计算 vkv^kvk 时应使用快速幂来求解以保证时间效率和取模正确性。
- 可以使用 mapmapmap 容器来存储 ci,dic_i,d_ici,di,使用 mapmapmap 同时不必在排序与去重,且判断冲突和顺序便利也能很方便的实现,但是对于每组测试数据要记得清空容器(建议在每组程序开始时清空,这样不容易遗漏情况;也可以在每组程序开始前创建容器,这样便不需要清空容器)。
参考代码
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
typedef long long LL;
map<int,int>mp;
int pows(int a,int k)
{LL ans=1;for (; k; k>>=1,a=(LL)a*a%mod)if (k&1) ans=(LL)ans*a%mod;return ans;
}
int main()
{int t,fl;scanf("%d",&t);while (t--){fl=0;int n,m,v;LL ans=1;scanf("%d%d%d",&n,&m,&v);for (int i=0; i<m; i++){int x,y;scanf("%d%d",&x,&y);if (mp[x]&&mp[x]!=y) fl=1;mp[x]=y;}if (fl){puts("0");mp.clear();continue;}auto last=mp.begin();ans=pows(v,last->first-1<<1);for (auto it=mp.begin(); it!=mp.end(); it++){if (it==last) continue;int l=last->first,r=it->first;int num=((pows(v,r-l<<1)-pows(v,r-l)+mod)%mod+pows(v,r-l-1))%mod;ans=ans*num%mod;last=it;}ans=ans*pows(v,n-last->first<<1)%mod;printf("%lld\n",ans);mp.clear();}return 0;
}
END
感谢观看,如有问题欢迎指出。
Experience\large \textit{\textbf {Experience}}Experience
注意到公式 f(k)=v2k−vk+vk−1f(k)=v^{2k}-v^k+v^{k-1}f(k)=v2k−vk+vk−1,减数是 vkv^kvk,而被减数是 v2kv^{2k}v2k,显然 v2k>vkv^{2k}>v^kv2k>vk,然而:
很显然,经过模运算,并不存在 v2k%mod>vk%modv^{2k}\%mod>v^k\%modv2k%mod>vk%mod 的大小关系。
更新日志
- 2025/09/21 开始书写本篇 CSDN 博客,并完稿发布。