【 线性筛 调和级数】P7281 [COCI 2020/2021 #4] Vepar|普及+

本文涉及知识点

数论:质数、最大公约数、菲蜀定理

P7281 [COCI 2020/2021 #4] Vepar

题目描述

给定两组正整数 { a , a + 1 , ⋯   , b } \{a,a+1,\cdots,b\} {a,a+1,⋯,b} 和 { c , c + 1 , ⋯   , d } \{c,c+1,\cdots,d\} {c,c+1,⋯,d}。判断 c ⋅ ( c + 1 ) ⋯ d c \cdot (c+1)\cdots d c⋅(c+1)⋯d 能否被 a ⋅ ( a + 1 ) ⋯ b a \cdot (a+1)\cdots b a⋅(a+1)⋯b 整除。

输入格式

第一行输入一个整数 t t t,表示数据组数。

接下来的 t t t 行,输入四个整数 a i , b i , c i , d i a_i,b_i,c_i,d_i ai,bi,ci,di。

输出格式

输出共 t t t 行。对于第 i i i 行,如果 c i ⋅ ( c i + 1 ) ⋯ d i c_i \cdot (c_i+1)\cdots d_i ci⋅(ci+1)⋯di 能够被 a i ⋅ ( a i + 1 ) ⋯ b i a_i \cdot (a_i+1)\cdots b_i ai⋅(ai+1)⋯bi 整除,就输出 DA,否则输出 NE

输入输出样例 #1

输入 #1

复制代码
2
9 10 3 6
2 5 7 9

输出 #1

复制代码
DA
NE

输入输出样例 #2

输入 #2

复制代码
6
1 2 3 4
1 4 2 3
2 3 1 4
1 3 2 4
19 22 55 57
55 57 19 22

输出 #2

复制代码
DA
NE
DA
DA
DA
DA

说明/提示

样例 1 解释

按照题意分别相乘得到 9 × 10 = 90 9 \times 10=90 9×10=90 和 3 × 4 × 5 × 6 = 360 3 \times 4 \times 5 \times 6=360 3×4×5×6=360。由于 90 90 90 能被 360 360 360 整除,因此输出 DA

我们得到 2 × 3 × 4 × 5 = 120 2 \times 3 \times 4 \times 5=120 2×3×4×5=120 和 7 × 8 × 9 = 504 7 \times 8 \times 9=504 7×8×9=504。而 120 120 120 不能被 504 504 504 整除,因此输出 NE

数据规模与约定

本题不采用捆绑评测,通过对应测试点就可以拿到对应的分数,但有若干个约束。

约束编号 分值 数据范围及约定
1 1 1 10 10 10 a i , b i , c i , d i ≤ 50 a_i,b_i,c_i,d_i \le 50 ai,bi,ci,di≤50
2 2 2 20 20 20 a i , b i , c i , d i ≤ 1000 a_i,b_i,c_i,d_i \le 1000 ai,bi,ci,di≤1000
3 3 3 10 10 10 a i = 1 a_i=1 ai=1
4 4 4 30 30 30

对于 100 % 100\% 100% 的数据, 1 ≤ t ≤ 10 1 \le t \le 10 1≤t≤10, 1 ≤ a i ≤ b i ≤ 10 7 1 \le a_i \le b_i \le 10^7 1≤ai≤bi≤107, 1 ≤ c i ≤ d i ≤ 10 7 1 \le c_i \le d_i \le 10^7 1≤ci≤di≤107。

说明

本题分值按 COCI 原题设置,满分 70 70 70。

题目译自 COCI2020-2021 CONTEST #4 T2 Vepar

线性筛 调和级数

M =1e7

所有用例初始化一次:

pri记录[1,M]间的质因数,x = pri.size(),大约1e6。

向量v[i]包括{i1,i2}表示i1的阶乘共有i2个质因数i。

tmp[j]记录包括质因数i的数量。

for( i :pri ){

for(int j =1; ij <= M ;j++){
v[i].emplace_back(j
i,tmp[j]+1)

tmp[i*j] = tmp[j]+1;

}

根据v[i] 清理tmp。注意 :如果全清,时间复杂度是O(n)

}

对于每个查询,枚举每个质因数:

通过二分查找[a,b]中此质因数的数量x1,[c,d]中的质因数数量x2。如果x2 > x1,返回false。

如果没有返回false,返回true。

初始化时间复杂度 :O(xlogM)

查询时间复杂度 :O(xlogM)

初始化的时候时间会超限,给向量分配空间太花时间了。

n的阶乘中因子p的数量:
∑ k : 1 p ⌊ n / k p ⌋ \sum_{k:1}^p \lfloor n/k^p \rfloor ∑k:1p⌊n/kp⌋

代码

核心代码

cpp 复制代码
#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 <bitset>
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 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;
}
class CCreatePrime {
public:
	CCreatePrime(int iMax) :m_isPrime(iMax + 1, true)
	{
		m_isPrime[0] = m_isPrime[1] = false;
		for (int i = 2; i <= iMax; i++)
		{
			if (m_isPrime[i])
			{
				m_vPrime.emplace_back(i);
			}
			for (const auto& n : m_vPrime)
			{
				if ((long long)n * i > iMax) { break; }
				m_isPrime[n * i] = false;
				if (0 == i % n) { break; }
			}
		}
	}
	vector<int> m_vPrime;
	vector<bool> m_isPrime;
};
class Solution {
public:
	vector<bool> Ans(vector<tuple<int, int, int, int>>& abcd) {
		Init();
		vector<bool> ans;
		for (const auto& [a, b, c, d] : abcd) {
			bool bCan = true;
			for (const auto& p : s_prime) {
				auto Cal = [&](int n) {
					int cnt = 0;
					for (long long k = p; k <= n; k *= p) {
						cnt += n / k;
					}
					return cnt;
				};
				if (Cal(d) - Cal(c - 1) < Cal(b) - Cal(a - 1)) { bCan = false; break; }
			}
			ans.emplace_back(bCan);
		}
		return ans;
	}
	void Init() {
		if (s_prime.size()) { return; }
		const int M = 10'000'000;
		s_prime = CCreatePrime(M).m_vPrime;
	}
	static vector<int> s_prime;
};

vector<int> Solution::s_prime;


int main() {
#ifdef _DEBUG
	freopen("a.in", "r", stdin);
#endif // DEBUG	
	ios::sync_with_stdio(0); cin.tie(nullptr);
	auto abcd = Read<tuple<int, int, int, int>>();
#ifdef _DEBUG		
	//printf("N=%d",n);
	//Out(abcd, "abcd=");
	//Out(strs2, ",strs2=");
	//Out(que, ",que=");
	/*Out(que, "que=");*/
#endif // DEBUG		
	auto res = Solution().Ans(abcd);	
	for (const auto& b : res)
	{
		cout << (b ? "DA" : "NE") << "\n";
	}
	return 0;
}

单元测试

cpp 复制代码
vector<tuple<int, int, int, int>> abcd;
		TEST_METHOD(TestMethod11)
		{
			abcd = { {9,10,3,6},{2,5,7,9} };
			auto res = Solution().Ans(abcd);
			AssertV({ true,false}, res);
		}
		TEST_METHOD(TestMethod12)
		{
			abcd = { {1,2,3,4},{1,4,2,3},{2,3,1,4},{1,3,2,4},{19,22,55,57},{55,57,19,22} };
			auto res = Solution().Ans(abcd);
			AssertV({ true,false,true,true,true,true }, 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++**实现。

相关推荐
zzzsde1 小时前
【Linux】线程概念与控制(1)线程基础与分页式存储管理
linux·运维·服务器·开发语言·算法
穿条秋裤到处跑1 小时前
每日一道leetcode(2026.04.23):等值距离和
算法·leetcode·职场和发展
少许极端2 小时前
算法奇妙屋(四十九)-贡献法
java·算法·leetcode·贡献法
叶子野格2 小时前
《C语言学习:数组》11
c语言·开发语言·c++·学习·visual studio
武帝为此2 小时前
【特征选择方法】
算法·数学建模
Little At Air2 小时前
C++priority_queue模拟实现
开发语言·数据结构·c++
程序员zgh2 小时前
C++ decltype 关键字 详解
c语言·开发语言·c++
XS0301062 小时前
Agent 记忆管理
大数据·人工智能·算法
探物 AI2 小时前
【感知·算法】一文综述医学图像分割:从经典 U-Net 到 Mamba 的范式跃迁
算法