1 条题解
-
0
这是一个为“连续子段的整除判定”题目设计的标准数据生成器。它包含了标准解法(用于生成
.out文件)和数据生成逻辑(用于生成.in文件)。这份代码会直接在当前目录下生成
1.in/1.out到10.in/10.out共20个文件,覆盖了从小数据、边界情况(如0、长度不足)到大规模数据的完整测试场景。数据生成器策略说明
为了保证测试数据的有效性,设计了以下10个测试点:
- TestCase 1 (Sample): 题目给出的样例,保证基础正确性。
- TestCase 2 (Small NO): 小规模数据,构造不存在解的情况。
- TestCase 3 (Zeros): 包含连续的 0,考察对 0 的处理( 是任何 的倍数)。
- TestCase 4 (Length Trap): 构造前缀和余数相同但距离为 1 的情况(如
[1, k, 2]),考察是否正确处理“长度至少为2”。 - TestCase 5 (Pigeonhole YES): ,根据抽屉原理必然存在同余前缀和,考察大规模下的正确判定。
- TestCase 6 (Large NO - Constructed): 大规模数据,通过构造(如全为 1 且 )强行让结果为 NO。
- TestCase 7 (Large K): 非常大(接近
INT_MAX),考察哈希表和取模的性能。 - TestCase 8 (Random Big): , ,随机性较强。
- TestCase 9 (Max Values): 元素值很大(接近 ),考察前缀和是否使用
long long避免溢出。 - TestCase 10 (Max N & K): 极限数据,, 。
C++ 数据生成器代码
请保存为
generator.cpp,编译运行即可。/** * 题目:连续子段的整除判定 - 数据生成器 * 功能:生成 1.in/1.out ~ 10.in/10.out * 环境:C++14 Standard */ #include <iostream> #include <fstream> #include <vector> #include <string> #include <random> #include <unordered_map> #include <algorithm> #include <chrono> using namespace std; // ========================================== // Part 1: 标准解法 (Solver) // 用于生成 .out 文件 // ========================================== string solve(int n, long long k, const vector<long long>& nums) { if (n < 2) return "NO"; // map: {remainder -> first_index} // 使用 unordered_map 保证 O(N) unordered_map<long long, int> mp; // 初始化:前缀和为0的情况,虚拟下标-1 mp[0] = -1; long long currentSum = 0; for (int i = 0; i < n; ++i) { currentSum += nums[i]; // 计算余数 long long remainder = currentSum % k; if (mp.count(remainder)) { int prevIndex = mp[remainder]; // 检查长度是否 >= 2 if (i - prevIndex >= 2) { return "YES"; } // 如果长度 < 2,不更新下标,保留最左边的以获得更长子段 } else { mp[remainder] = i; } } return "NO"; } // ========================================== // Part 2: 数据生成工具 // ========================================== mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); // 生成随机整数 [min, max] long long randInt(long long min, long long max) { uniform_int_distribution<long long> dist(min, max); return dist(rng); } // 写入文件辅助函数 void writeData(int caseId, int n, long long k, const vector<long long>& nums) { string inFileName = to_string(caseId) + ".in"; string outFileName = to_string(caseId) + ".out"; // 写入 .in ofstream inFile(inFileName); inFile << n << " " << k << endl; for (int i = 0; i < n; ++i) { inFile << nums[i] << (i == n - 1 ? "" : " "); } inFile << endl; inFile.close(); // 计算并写入 .out string ans = solve(n, k, nums); ofstream outFile(outFileName); outFile << ans << endl; outFile.close(); cout << "Generated Case " << caseId << ": N=" << n << ", K=" << k << " -> " << ans << endl; } // ========================================== // Part 3: 生成逻辑主体 // ========================================== int main() { // --- 1. 样例数据 --- { int n = 5; long long k = 6; vector<long long> nums = {23, 2, 4, 6, 7}; writeData(1, n, k, nums); } // --- 2. 小规模 NO --- { // 1, 2, 3, 4, 5 的前缀和是 1, 3, 6, 10, 15 // K=100,余数都不重复 int n = 5; long long k = 100; vector<long long> nums = {1, 2, 3, 4, 5}; writeData(2, n, k, nums); } // --- 3. 包含0的情况 (Zeroes) --- { // 0是任何K的倍数,连续两个0必然YES,或者数和0组合 int n = 10; long long k = 7; vector<long long> nums(n); for(int i=0; i<n; ++i) nums[i] = (i == 5 || i == 6) ? 0 : randInt(1, 10); writeData(3, n, k, nums); } // --- 4. 长度陷阱 (Length < 2) --- { // 构造:前缀和余数重复,但距离为1 // 例如 K=10, 数组 [1, 10, 2] // Pre: 1 (idx 0), 11 (idx 1), 13 (idx 2) // Mods: 1, 1, 3 // Mod 1 重复,indices: 0, 1 -> dist = 1 (Too short) -> NO int n = 3; long long k = 10; vector<long long> nums = {1, 10, 2}; writeData(4, n, k, nums); } // --- 5. 抽屉原理 YES (N >= K) --- { // 当 N >= K 时,前缀和模K只有 K 种取值,N个前缀和必然有重复 // 除非运气极差所有重复都是相邻的(概率极低),大概率 YES int n = 1000; long long k = 500; vector<long long> nums(n); for(int i=0; i<n; ++i) nums[i] = randInt(1, 1000); writeData(5, n, k, nums); } // --- 6. 构造大规模 NO --- { // 构造:让前缀和严格递增且 < K // 全是 1,K > N int n = 20000; long long k = 50000; vector<long long> nums(n, 1); writeData(6, n, k, nums); } // --- 7. Large K (随机) --- { int n = 5000; long long k = 2000000000LL; // 2 * 10^9 vector<long long> nums(n); for(int i=0; i<n; ++i) nums[i] = randInt(0, 100000); writeData(7, n, k, nums); } // --- 8. Random Big Data (YES/NO Mixed) --- { int n = 100000; // 10^5 long long k = 7919; // 素数 vector<long long> nums(n); for(int i=0; i<n; ++i) nums[i] = randInt(0, 10000); writeData(8, n, k, nums); } // --- 9. 大数值元素 (Max Values) --- { // 考察 long long 溢出(虽然题目保证前缀和在64位内,但生成时要注意) // 题目数据范围 a_i <= 10^9 int n = 50000; long long k = 1234567; vector<long long> nums(n); for(int i=0; i<n; ++i) nums[i] = randInt(100000000, 1000000000); writeData(9, n, k, nums); } // --- 10. 极限数据 (Max Constraints) --- { int n = 100000; long long k = 2147483647LL; // INT_MAX vector<long long> nums(n); // 这里随机生成,由于 K 很大,可能是 NO,也可能是 YES(取决于随机碰撞) for(int i=0; i<n; ++i) nums[i] = randInt(0, 1000000000); writeData(10, n, k, nums); } cout << "All 10 test cases generated successfully!" << endl; return 0; }使用指南
- 编译:
g++ generator.cpp -o generator -std=c++14 -O2 - 运行:
Windows下直接双击
generator.exe或命令行运行generator。 Linux/Mac下运行./generator。 - 结果:
程序运行后,你的文件夹中会出现
1.in~10.in以及对应的答案1.out~10.out。 - 注意:
- 代码中使用了
<random>和std::mt19937_64确保随机数质量。 solve函数已针对题目逻辑进行了完整实现,包括对 的处理和长度限制的处理。- TestCase 6 特意构造了全为 1 且 的情况,确保生成一个大规模的
NO数据,防止随机数据全是YES。
- 代码中使用了
- 1
信息
- ID
- 19327
- 时间
- 1000ms
- 内存
- 32MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 1
- 已通过
- 1
- 上传者