当前位置: 首页 > news >正文

【组合数学】P11362 [NOIP2024] 遗失的赋值|普及+

本文涉及知识点

组合数学汇总

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

输入 #1

3
2 1 2
1 1
2 2 2
1 1
2 2
2 2 2
1 1
1 2

输出 #1

4
3
0

说明/提示

【样例 1 解释】

  • 对于第一组测试数据,所有可能的 ( a 1 , b 1 ) (a_1, b_1) (a1,b1) 取值的组合 ( 1 , 1 ) , ( 1 , 2 ) , ( 2 , 1 ) , ( 2 , 2 ) (1, 1), (1, 2), (2, 1), (2, 2) (1,1),(1,2),(2,1),(2,2) 都满足限制。例如, ( a 1 , b 1 ) = ( 1 , 1 ) (a_1, b_1) = (1, 1) (a1,b1)=(1,1) 时, ( x 1 , x 2 ) = ( 1 , 1 ) (x_1, x_2) = (1, 1) (x1,x2)=(1,1) 满足所有限制,而 ( a 1 , b 1 ) = ( 2 , 2 ) (a_1, b_1) = (2, 2) (a1,b1)=(2,2) 时, ( x 1 , x 2 ) = ( 1 , 1 ) (x_1, x_2) = (1, 1) (x1,x2)=(1,1) ( x 1 , x 2 ) = ( 1 , 2 ) (x_1, x_2) = (1, 2) (x1,x2)=(1,2) 均满足所有限制。
  • 对于第二组测试数据,只有 ( x 1 , x 2 ) = ( 1 , 2 ) (x_1, x_2) = (1, 2) (x1,x2)=(1,2) 一种可能的变量赋值,因此只有 ( a 1 , b 1 ) = ( 1 , 1 ) (a_1, b_1) = (1, 1) (a1,b1)=(1,1) 不满足限制,其余三种赋值均满足限制。
  • 对于第三组测试数据,不存在一种变量赋值同时满足 x 1 = 1 x_1 = 1 x1=1 x 1 = 2 x_1 = 2 x1=2,因此也不存在满足限制的 ( a 1 , b 1 ) (a_1, b_1) (a1,b1)

【样例 2】

见选手目录下的 assign/assign2.inassign/assign2.ans

该样例共有 10 10 10 组测试数据,其中第 i i i 1 ≤ i ≤ 10 1 \leq i \leq 10 1i10)组测试数据满足数据范围中描述的测试点 i i i 的限制。

【样例 3】

见选手目录下的 assign/assign3.inassign/assign3.ans

该样例共有 10 10 10 组测试数据,其中第 i i i 1 ≤ i ≤ 10 1 \leq i \leq 10 1i10)组测试数据满足数据范围中描述的测试点 i + 10 i + 10 i+10 的限制。

【数据范围】

对于所有的测试数据,保证:

  • 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 \leq n m ≤ m \leq m v ≤ v \leq v特殊性质
1 , 2 1, 2 1,2 6 6 6 6 6 6 2 2 2
3 3 3 9 9 9 9 9 9 2 2 2
4 , 5 4, 5 4,5 12 12 12 12 12 12 2 2 2
6 6 6 1 0 3 10^3 103 1 1 1 1 0 3 10^3 103
7 7 7 1 0 5 10^5 105 1 1 1 1 0 5 10^5 105
8 , 9 8,9 8,9 1 0 9 10^9 109 1 1 1 1 0 9 10^9 109
10 10 10 1 0 3 10^3 103 1 0 3 10^3 103 1 0 3 10^3 103A
11 11 11 1 0 4 10^4 104 1 0 4 10^4 104 1 0 4 10^4 104A
12 12 12 1 0 5 10^5 105 1 0 5 10^5 105 1 0 5 10^5 105A
13 13 13 1 0 4 10^4 104 1 0 3 10^3 103 1 0 4 10^4 104B
14 14 14 1 0 6 10^6 106 1 0 4 10^4 104 1 0 6 10^6 106B
15 , 16 15, 16 15,16 1 0 9 10^9 109 1 0 5 10^5 105 1 0 9 10^9 109B
17 17 17 1 0 4 10^4 104 1 0 3 10^3 103 1 0 4 10^4 104
18 18 18 1 0 6 10^6 106 1 0 4 10^4 104 1 0 6 10^6 106
19 , 20 19, 20 19,20 1 0 9 10^9 109 1 0 5 10^5 105 1 0 9 10^9 109

特殊性质 A:保证 m = n m = n m=n,且对于任意的 j j j 1 ≤ j ≤ m 1 \leq j \leq m 1jm),都有 c j = j c_j = j cj=j

特殊性质 B:保证 d j = 1 d_j = 1 dj=1

组合数学

预处理

下标改成从0开始。
v={ c i , d i c_i,d_i ci,di}排序去重,如果相邻的两项 c i c_i ci相同直接返回0。
令v[i]={e_i,f_i}
0 ≤ j < e 0 , a j 和 b j 0 \le j< e_0,a_j和b_j 0j<e0ajbj可以任意选择。共 v 2 × e 0 v^{2\times e0} v2×e0
e b a c k ≤ j < N − 1 , a j 和 b j e_{back} \le j <N-1,a_j和b_j ebackj<N1ajbj可以任意选择。共 v 2 × ( N − 1 − e b a c k ) v^{2\times (N-1-e_back)} v2×(N1eback)
∀ e i ≤ j < e i + 1 \forall e_i \le j < e_{i+1} eij<ei+1 共有 x = e i + 1 − e i , c 0 = v 2 × x x=e_{i+1}-e_i,c0=v^{2 \times x} x=ei+1ei,c0=v2×x种选择。
发生冲突的方案c1 = v x − 1 ( v − 1 ) =v^{x-1}(v-1) =vx1(v1)
冲突的方案: a e i = f i , b e i = a e i + 1 = 任意 ⋯ b e i + 1 − 1 ≠ f e i + 1 a_{e_i}=f_i,b_{e_i}=a_{e_i+1}=任意 \cdots b_{e_{i+1}-1} \neq f_{e_{i+1}} aei=fi,bei=aei+1=任意bei+11=fei+1
合法方案=c0-c1。
所有区域相乘便是答案。

代码

核心代码

#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>
#include<array>#include <bitset>
#include <chrono>
using namespace std::chrono;
using namespace std;template<class T1, class T2>
std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {in >> pr.first >> pr.second;return in;
}template<class T1, class T2, class T3 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t);return in;
}template<class T1, class T2, class T3, class T4 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);return in;
}template<class T1, class T2, class T3, class T4, class T5 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4, T5>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t) ;return in;
}template<class T1, class T2, class T3, class T4, class T5, class T6 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4, T5, T6>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t) >> get<5>(t) ;return in;
}template<class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4, T5, T6, T7>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t) >> get<5>(t) >> get<6>(t);return in;
}template<class T = int>
vector<T> Read() {int n;cin >> n;vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}
template<class T = int>
vector<T> ReadNotNum() {vector<T> ret;T tmp;while (cin >> tmp) {ret.emplace_back(tmp);if ('\n' == cin.get()) { break; }}return ret;
}template<class T = int>
vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}template<int N = 1'000'000>
class COutBuff
{
public:COutBuff() {m_p = puffer;}template<class T>void write(T x) {int num[28], sp = 0;if (x < 0)*m_p++ = '-', x = -x;if (!x)*m_p++ = 48;while (x)num[++sp] = x % 10, x /= 10;while (sp)*m_p++ = num[sp--] + 48;AuotToFile();}void writestr(const char* sz) {strcpy(m_p, sz);m_p += strlen(sz);AuotToFile();}inline void write(char ch){*m_p++ = ch;AuotToFile();}inline void ToFile() {fwrite(puffer, 1, m_p - puffer, stdout);m_p = puffer;}~COutBuff() {ToFile();}
private:inline void AuotToFile() {if (m_p - puffer > N - 100) {ToFile();}}char  puffer[N], * m_p;
};template<int N = 1'000'000>
class CInBuff
{
public:inline CInBuff() {}inline CInBuff<N>& operator>>(char& ch) {FileToBuf();while (('\r' == *S) || ('\n' == *S) || (' ' == *S)) { S++; }//忽略空格和回车ch = *S++;return *this;}inline CInBuff<N>& operator>>(int& val) {FileToBuf();int x(0), f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行		return *this;}inline CInBuff& operator>>(long long& val) {FileToBuf();long long x(0); int f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行return *this;}template<class T1, class T2>inline CInBuff& operator>>(pair<T1, T2>& val) {*this >> val.first >> val.second;return *this;}template<class T1, class T2, class T3>inline CInBuff& operator>>(tuple<T1, T2, T3>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val);return *this;}template<class T1, class T2, class T3, class T4>inline CInBuff& operator>>(tuple<T1, T2, T3, T4>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val) >> get<3>(val);return *this;}template<class T = int>inline CInBuff& operator>>(vector<T>& val) {int n;*this >> n;val.resize(n);for (int i = 0; i < n; i++) {*this >> val[i];}return *this;}template<class T = int>vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {*this >> ret[i];}return ret;}template<class T = int>vector<T> Read() {vector<T> ret;*this >> ret;return ret;}
private:inline void FileToBuf() {const int canRead = m_iWritePos - (S - buffer);if (canRead >= 100) { return; }if (m_bFinish) { return; }for (int i = 0; i < canRead; i++){buffer[i] = S[i];//memcpy出错			}m_iWritePos = canRead;buffer[m_iWritePos] = 0;S = buffer;int readCnt = fread(buffer + m_iWritePos, 1, N - m_iWritePos, stdin);if (readCnt <= 0) { m_bFinish = true; return; }m_iWritePos += readCnt;buffer[m_iWritePos] = 0;S = buffer;}int m_iWritePos = 0; bool m_bFinish = false;char buffer[N + 10], * S = buffer;
};template<long long MOD = 1000000007, class T1 = int, class T2 = long long>
class C1097Int
{
public:C1097Int(T1 iData = 0) :m_iData(iData% MOD){}C1097Int(T2 llData) :m_iData(llData% MOD) {}C1097Int  operator+(const C1097Int& o)const{return C1097Int(((T2)m_iData + o.m_iData) % MOD);}C1097Int& operator+=(const C1097Int& o){m_iData = ((T2)m_iData + o.m_iData) % MOD;return *this;}C1097Int& operator-=(const C1097Int& o){m_iData = ((T2)MOD + m_iData - o.m_iData) % MOD;return *this;}C1097Int  operator-(const C1097Int& o)const{return C1097Int(((T2)MOD + m_iData - o.m_iData) % MOD);}C1097Int  operator*(const C1097Int& o)const{return((T2)m_iData * o.m_iData) % MOD;}C1097Int& operator*=(const C1097Int& o){m_iData = ((T2)m_iData * o.m_iData) % MOD;return *this;}C1097Int  operator/(const C1097Int& o)const{return *this * o.PowNegative1();}C1097Int& operator/=(const C1097Int& o){*this *= o.PowNegative1();return *this;}bool operator==(const C1097Int& o)const{return m_iData == o.m_iData;}bool operator<(const C1097Int& o)const{return m_iData < o.m_iData;}C1097Int pow(T2 n)const{C1097Int iRet = (T1)1, iCur = *this;while (n){if (n & 1){iRet *= iCur;}iCur *= iCur;n >>= 1;}return iRet;}C1097Int PowNegative1()const{return pow(MOD - 2);}T1 ToInt()const{return ((T2)m_iData + MOD) % MOD;}
private:T1 m_iData = 0;;
};typedef C1097Int<> BI;
class Solution {
public:int Ans(const int N, const int v, vector<pair<int, int>>& cd) {sort(cd.begin(), cd.end());cd.erase(unique(cd.begin(), cd.end()), cd.end());for (auto& [c, d] : cd) { c--; }for (int i = 1; i < cd.size(); i++) {if (cd[i].first == cd[i - 1].first) { return 0; }}BI ans = BI(v).pow(2 * cd[0].first);ans *= BI(v).pow(2 * (N - 1 - cd.back().first));for (int i = 0; i + 1 < cd.size(); i++) {const int x = cd[i + 1].first - cd[i].first;ans *= (BI(v).pow(2 * x) - BI(v).pow(x - 1) * (v - 1));}return ans.ToInt();}
};
int main() {
#ifdef _DEBUGfreopen("a.in", "r", stdin);
#endif // DEBUG	ios::sync_with_stdio(0); cin.tie(nullptr);//CInBuff<> in; COutBuff<10'000'000> ob;int T;cin >> T;while(T--){ int n, m, v;cin >> n >> m >> v;auto cd = Read<pair<int, int>>(m);
#ifdef _DEBUG	printf("N=%d,v=%d", n,v);Out(cd, ",cd=");//Out(B, ",B=");//Out(que, ",que=");
#endif // DEBUG		Solution slu;auto res = Solution().Ans(n,v,cd);cout << res << "\n";}return 0;
}

单元测试

vector<pair<int, int>> cd;TEST_METHOD(TestMethod11){N = 2, v = 2, cd = { {1,1} };auto res = Solution().Ans(N,v,cd);AssertEx(4, res);}TEST_METHOD(TestMethod12){N = 2, v = 2, cd = { {1,1},{2,2} };auto res = Solution().Ans(N, v, cd);AssertEx(3, res);}TEST_METHOD(TestMethod13){N = 2, v = 2, cd = { {1,1},{1,2} };auto res = Solution().Ans(N, v, cd);AssertEx(0, res);}

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

http://www.dtcms.com/a/264089.html

相关文章:

  • 事务隔离级别深度解析:机制、语法与实战指
  • 力扣74 搜索二维矩阵
  • [密码学实战]深入解析ASN.1和DER编码:以数字签名值为例(三十一)
  • UniApp完全支持快应用QUICKAPP-以及如何采用 Uni 模式开发发行快应用优雅草卓伊凡
  • 从 Copilot 到 通用 Agent : 大厂在 AI Coding 上的应用和挑战
  • 华为云开始了“开发者空间 AI Agent 开发”活动
  • Anthropic 开源 LLM“电路追踪器”:首次可视化语言模型的“推理路径”!
  • SQLite与MySQL:嵌入式与客户端-服务器数据库的权衡
  • 使用mavros启动多机SITL仿真
  • 9-2 MySQL 分析查询语句:EXPLAIN(详细说明)
  • react-数据Mock实现——json-server
  • Jenkins 插件深度应用:让你的CI/CD流水线如虎添翼 [特殊字符]
  • 华锐互动:全方位定制化 VR 内容制作服务流程剖析​
  • [Python 基础课程]字符串
  • Redis集群数据流解析:从分层设计到一致性难题破解
  • Vue3 中 Excel 导出的性能优化与实战指南
  • A模块 系统与网络安全 第三门课 网络通信原理-3
  • Badoo×亚矩云手机:社交约会革命的“云端心跳加速剂“
  • 论文阅读:Align and Prompt (ALPRO 2021.12)
  • 狂神说 - Mybatis 学习笔记 --下
  • SVN 分支管理(本文以Unity项目为例)
  • 【C++】inline的作用
  • 齿轮的齿厚极限偏差如何确定?一起学习一下
  • Vue3——富文本
  • 地震灾害的模拟
  • win11,visual studio 2022,配置dcmtk,opencv
  • vue vxe-table 自适应列宽,根据内容自适应宽度的2种使用方式
  • MySQL非阻塞创建索引的方法
  • golang generic 2022-04-13
  • Linux 系统重启 reboot与重置reset深度解析