【NOIP 2024 T2】遗失的赋值

NOIP2024遗失赋值解法

【NOIP 2024 T2】遗失的赋值


NOIP 专栏:NOIP 2024 T2
算法竞赛:组合数学、数学
题目链接:洛谷 P11362【NOIP2024】遗失的赋值
本题专栏:(一)公式推导

题目描述:
小 F 有 n n n 个变量 x 1 , x 2 , … , x n x_1, x_2, \ldots , x_n x1,x2,,xn。每个变量可以取 1 1 1 v v v 的整数取值。
小 F 在这 n n n 个变量之间添加了 n − 1 n - 1 n1 条二元限制,其中第 i i i 1 ≤ i ≤ n − 1 1 \leq i \leq n - 1 1in1)条限制为:若 x i = a i x_i = a_i xi=ai,则要求 x i + 1 = b i x_{i+1} = b_i xi+1=bi a i a_i ai b i b_i bi 1 1 1 v v v 之间的整数;当 x i ≠ a i x_i \neq a_i xi=ai 时,第 i i i 条限制对 x i + 1 x_{i+1} xi+1 的值不做任何约束。除此之外,小 F 还添加了 m m m 条一元限制,其中第 j j j 1 ≤ j ≤ m 1 \leq j \leq m 1jm)条限制为: x c j = d j x_{c_j} = d_j xcj=dj
小 F 记住了所有 c j c_j cj d j d_j dj 的值,但把所有 a i a_i ai b i b_i bi 的值都忘了。同时小 F 知道:存在给每一个变量赋值的方案同时满足所有这些限制。
现在小 F 想知道,有多少种 a i , b i a_i, b_i ai,bi 1 ≤ i ≤ n − 1 1 \leq i \leq n - 1 1in1)取值的组合,使得能够确保至少存在一种给每个变量 x i x_i xi 赋值的方案可以同时满足所有限制。由于方案数可能很大,小 F 只需要你输出方案数对 1 0 9 + 7 10^9 + 7 109+7 取模的结果。

输入格式:
本题包含多组测试数据
输入的第一行包含一个整数 T T T,表示测试数据的组数。
接下来包含 T T T 组数据,每组数据的格式如下:
第一行包含三个整数 n , m , v n, m, v n,m,v,分别表示变量个数、一元限制个数和变量的取值上限。
接下来 m m m 行,第 j j j 行包含两个整数 c j , d j c_j, d_j cj,dj,描述一个一元限制。
输出格式:
对于每组测试数据输出一行,包含一个整数,表示方案数对 1 0 9 + 7 10^9 + 7 109+7 取模的结果。

数据范围:

  • 1 ≤ T ≤ 10 1 \leq T \leq 10 1T10
  • 1 ≤ n ≤ 1 0 9 1 \leq n \leq 10^9 1n109 1 ≤ m ≤ 1 0 5 1 \leq m \leq 10^5 1m105 2 ≤ v ≤ 1 0 9 2 \leq v \leq 10^9 2v109
  • 对于任意的 j j j 1 ≤ j ≤ m 1 \leq j \leq m 1jm),都有 1 ≤ c j ≤ n 1 \leq c_j \leq n 1cjn 1 ≤ d j ≤ v 1 \leq d_j \leq v 1djv


题目大意


对于 n n n 个变量 x i , 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∣1yv,yZ},变量的取值要满足 n − 1 n-1 n1 个二元限制和 m m m 个一元限制,限制如下:

  • a i , b i , i ∈ [ 1 , n − 1 ] a_i,b_i,i\in [1,n-1] ai,bi,i[1,n1] 为二元限制参数,取值范围为 { y ∣ 1 ≤ y ≤ v , y ∈ Z } \{y | 1\le y\le v,y\in \mathbb{Z}\} {y∣1yv,yZ},限制为:如果 x i = a i x_i=a_i xi=ai 则要求 x i + 1 = b i x_{i+1}=b_i xi+1=bi
  • c j , d j , 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∣1yv,yZ},限制为: x c j = d j x_{c_j}=d_j xcj=dj

现在已知 m m m 组一元限制的参数 c j , d j c_j,d_j cj,dj,而对于 n − 1 n-1 n1 组二元限制参数 a i , b i a_i,b_i ai,bi 是未知的,现要求出对于参数 a i , b i , i ∈ [ 1 , n − 1 ] a_i,b_i,i\in [1,n-1] ai,bi,i[1,n1] 取值的组合的方案数,每种组合要使得至少存在一种给每个变量 x i x_i xi 赋值的方案是满足所有限制的(一元、二元限制),方案数对 1 0 9 + 7 10^9+7 109+7 取模。


题目分析


根据题目所述,容易知道:

  • 如果一元限制之间有冲突,则方案数为 0 0 0,即当 i ≠ j i\ne j i=j 时,若存在 c i = c j c_i=c_j ci=cj,而 d i ≠ d j d_i\ne d_j di=dj,则方案数为 a n s = 0 ans=0 ans=0
  • 对于一对连续的变量 x i , x i + 1 x_i,x_{i+1} xi,xi+1,如果两者均没有一元限制,那么 a i , b i a_i,b_i ai,bi 的取值组合方案数为 v 2 v^2 v2,进而对于一个长度为 n n n 且没有一元限制的变量 x i , i ∈ [ 1 , n ] x_i,i\in [1,n] xi,i[1,n] 序列,由乘法原理可知,参数 a i , b i , i ∈ [ 1 , n − 1 ] a_i,b_i,i\in [1,n-1] ai,bi,i[1,n1] 满足要求的组合方案数为 a n s = v 2 ( n − 1 ) ans=v^{2(n-1)} ans=v2(n1)
  • 对于一个长度为 n n n 且仅左端点有一元限制的变量 x i , i ∈ [ 1 , n ] x_i,i\in [1,n] xi,i[1,n] 序列,其方案数也为 a n s = v 2 ( n − 1 ) ans=v^{2(n-1)} ans=v2(n1),因为左端点有一元限制,就相当于确定左端点变量的值,而二元限制是对于前一个数满足条件则限制后一个数,所以仅左端点存在一元限制并无实际作用意义。
  • 对于一个长度为 n n n 且仅右端点有一元限制的变量 x i , i ∈ [ 1 , n ] x_i,i\in [1,n] xi,i[1,n] 序列,其方案数也为 a n s = v 2 ( n − 1 ) ans=v^{2(n-1)} ans=v2(n1),与仅左端点存在一元限制情况同理,可以从右向左来确定二元限制,这样就相当于仅左端点存在一元限制。

题目思路


Way   of   Thinking \large \textit{\textbf {Way of Thinking}} Way of Thinking

对于一个长度为 n n n 且仅左右端点有一元限制的变量 x i , x 2 , x 3 , ⋯   , x n − 2 , x n − 1 , x n x_i,x_2,x_3,\cdots,x_{n-2},x_{n-1},x_n xi,x2,x3,,xn2,xn1,xn 序列,存在 k k k 个二元限制( k = n − 1 k=n-1 k=n1),设其方案数为 f ( k ) f(k) f(k)

  • 对于 x 1 , x 2 x_1,x_2 x1,x2 之间的二元限制 ( a 1 , b 1 ) (a_1,b_1) (a1,b1) 如果使 a 1 = x 1 a_1=x_1 a1=x1,则要 x 2 = b 2 x_2=b_2 x2=b2,此时 a 1 a_1 a1
    存在一种方案,而 b 1 b_1 b1 v v v 种方案,故第一对二元限制 ( a 1 , b 1 ) (a_1,b_1) (a1,b1) v v v 种方案,这时相当于给 x 2 x_2 x2
    添加了一元限制,故序列的方案数为 v × f ( k − 1 ) v\times f(k-1) v×f(k1)
  • 如果使 a 1 ≠ x 1 a_1\ne x_1 a1=x1,这样 a 1 a_1 a1 存在 v − 1 v-1 v1 种方案, b 1 b_1 b1 v v v 种方案,故第一对二元限制 ( a 1 , b 1 ) (a_1,b_1) (a1,b1) v × ( v − 1 ) v\times (v-1) v×(v1) 种方案,这时对于 i ≥ 2 i\ge 2 i2 x i x_i xi 序列相当于变成了一个仅右端点存在一元限制的变量序列 x 2 , x 3 , ⋯   , x n − 2 , x n − 1 , x n x_2,x_3,\cdots,x_{n-2},x_{n-1},x_n x2,x3,,xn2,xn1,xn,对于这个序列方案数有 v 2 ( k − 1 ) v^{2(k-1)} v2(k1) 种,故这种情况的方案数为 v × ( v − 1 ) × v 2 ( k − 1 ) v\times (v-1)\times v^{2(k-1)} v×(v1)×v2(k1),即 v 2 k − v 2 k − 1 v^{2k}-v^{2k-1} v2kv2k1

特殊的,对于 k k k 取值的边界,当 k = 1 k=1 k=1 时, f ( x ) = v × ( v − 1 ) + 1 = v 2 − v + 1 f(x)=v\times (v-1)+1=v^2-v+1 f(x)=v×(v1)+1=v2v+1

综上所述, f ( k ) = v 2 k − v 2 k − 1 + v × f ( k − 1 ) f(k)=v^{2k}-v^{2k-1}+v\times f(k-1) f(k)=v2kv2k1+v×f(k1)。这样就有了一个方案数的递推式,然而如果递推地求解时间复杂度有些高,那么试一试能否将 f ( k ) f(k) f(k) 变成一个关于 k k k 的一个函数( v v v 作为常量)。

f ( k ) f(k) f(k) 展开:

f ( k ) = v 2 k − v 2 k − 1 + v × f ( k − 1 ) = v 2 k − v 2 k − 1 + v × ( v 2 x − 2 − v 2 x − 3 + v × f ( k − 2 ) ) = v 2 k − v 2 k − 1 + v 2 x − 1 − v 2 x − 2 + v 2 × f ( k − 2 ) = v 2 k − v 2 x − 2 + v 2 × f ( k − 2 ) = v 2 k − v 2 k − 2 + v 2 × ( v 2 x − 4 − v 2 x − 5 + v × f ( k − 3 ) ) = v 2 k − v 2 k − 2 + v 2 x − 2 − v 2 x − 3 + v 3 × f ( k − 3 ) = v 2 k − v 2 x − 3 + v 3 × 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)=v2kv2k1+v×f(k1)=v2kv2k1+v×(v2x2v2x3+v×f(k2))=v2kv2k1+v2x1v2x2+v2×f(k2)=v2kv2x2+v2×f(k2)=v2kv2k2+v2×(v2x4v2x5+v×f(k3))=v2kv2k2+v2x2v2x3+v3×f(k3)=v2kv2x3+v3×f(k3)=

l i n e ( 4 ) , l i n e ( 7 ) line(4),line(7) line(4),line(7) 行可以得出 f ( k ) f(k) f(k) f ( k − t ) f(k-t) f(kt) 的关系:

f ( k ) = v 2 k − v 2 k − t + v t × f ( k − t ) f(k)=v^{2k}-v^{2k-t}+v^t\times f(k-t) f(k)=v2kv2kt+vt×f(kt)

为消去 t t t,将 t = k − 1 t=k-1 t=k1 代入得:

f ( k ) = v 2 k − v 2 k − t + v t × f ( k − t ) = v 2 k − v 2 k − ( k − 1 ) + v k − 1 × f ( k − ( k − 1 ) ) = v 2 k − v k + 1 + v k − 1 × f ( 1 ) = v 2 k − v k + 1 + v k − 1 × ( v 2 − v + 1 ) = v 2 k − v k + 1 + v k + 1 − v k + v k − 1 = v 2 k − v k + v k − 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)=v2kv2kt+vt×f(kt)=v2kv2k(k1)+vk1×f(k(k1))=v2kvk+1+vk1×f(1)=v2kvk+1+vk1×(v2v+1)=v2kvk+1+vk+1vk+vk1=v2kvk+vk1

故得知:

f ( k ) = v 2 k − v k + v k − 1 f(k)=v^{2k}-v^k+v^{k-1} f(k)=v2kvk+vk1


题目做法


Specific   Solution \large \textit{\textbf {Specific Solution}} Specific Solution

对于每组测试数据:

  1. 读入并存储 m m m 个一元限制,判断一元限制之间是否冲突(若冲突则输出 0 0 0 并进行下一轮数据);
  2. 将一元限制按 c i , i ∈ [ 1 , m ] c_i,i\in [1,m] ci,i[1,m] 升序排序并去重,得到 c i , i ∈ [ 1 , m ′ ] c_i,i\in [1,m'] ci,i[1,m]
  3. 计算变量序列 x [ 1 ∼ c 1 ] x[1\sim c_1] x[1c1] 的方案数 v 2 ( c 1 − 1 ) v^{2(c_1-1)} v2(c11) x [ c m ′ ∼ n ] x[c_{m'}\sim n] x[cmn] 的方案数 v 2 ( n − c m ′ ) v^{2(n-c_{m'})} v2(ncm),根据乘法原理将两者相乘得到 a n s ans ans
  4. 遍历序列 c [ 1 ∼ m ′ ] c[1\sim m'] c[1m],对于每个 c i , i ∈ [ 1 , m ′ − 1 ] c_i,i\in [1,m'-1] ci,i[1,m1],使 a n s = a n s × f ( c i + 1 − c i ) ans=ans\times f(c_{i+1}-c_i) ans=ans×f(ci+1ci),得到最终方案数 a n s ans ans

注意:

  • 在公式 f ( k ) = v 2 k − v k + v k − 1 f(k)=v^{2k}-v^k+v^{k-1} f(k)=v2kvk+vk1 中存在含有模运算的减法,在取模之前需要加上模数(这很重要)。
  • 计算 v k v^k vk 时应使用快速幂来求解以保证时间效率和取模正确性。
  • 可以使用 m a p map map 容器来存储 c i , d i c_i,d_i ci,di,使用 m a p map map 同时不必在排序与去重,且判断冲突和顺序便利也能很方便的实现,但是对于每组测试数据要记得清空容器(建议在每组程序开始时清空,这样不容易遗漏情况;也可以在每组程序开始前创建容器,这样便不需要清空容器)。

参考代码


#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 ) = v 2 k − v k + v k − 1 f(k)=v^{2k}-v^k+v^{k-1} f(k)=v2kvk+vk1,减数是 v k v^k vk,而被减数是 v 2 k v^{2k} v2k,显然 v 2 k > v k v^{2k}>v^k v2k>vk,然而:

1

2

3

4

很显然,经过模运算,并不存在 v 2 k % m o d > v k % m o d v^{2k}\%mod>v^k\%mod v2k%mod>vk%mod 的大小关系。

更新日志

  • 2025/09/21 开始书写本篇 优快云 博客,并完稿发布。
  • 2025/10/12 对本篇 优快云 进行了微调与修改,并开启了本题目专栏项目(致力于多种解法)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HAH-HAH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值