• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
ABC 280 D - Factorial and Multiple

题目传送门

Lemma

Legendre 定理

在正数\(n!\)的质因数分解中, 质数\(p\) 的指数记作\(v_p(n!)\),则有等式\(v_p(n!)=\sum\limits_{j=1}^{\infty} \lfloor\frac{n}{p^k} \rfloor\)

LL f(LL n, LL p) {
	if (n == 0) return 0;
	n /= p;
	return n + f(n, p);
}

思路

对于给定的K求其最小数N满足\(K \mid N!\) , 首先对于满足该条件的\(N\), 有以下推论

  1. 任意的\(K \mid X!\) , 其中 \(X>=N\)

  2. 将\(K\)素因数分解 , 那么其每个素因数的幂数均小于X素因数分解中该数的幂数

由此,我们可以得到进一步结论:

  1. 当\(1 \leq X < N\)时, 那么K的素因数在X中要么不存在,要么在X中其素因数的幂数小于K中的幂数, 可以总结为在X中的素因数小于K中的素因数幂次(不存在时,幂次为0)。 当\(N \leq X\) 时,其素因数幂次均满足大于等于K中的幂次。

由此,我们可以得到二分的做法

时间复杂度\(O(\sqrt k)\)

#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <functional>
#include <utility>
#include <unordered_set>
#include <unordered_map>
#define INF 0x3f3f3f3f
#define IOS ios::sync_with_stdio(false);
#define rep(i, j, k) for(int i = j; i <= k; ++ i)
#define per(i, j, k) for(int i = j; i >= k; -- i)
#define dbg1(a) cout << a << endl;
#define dbg2(a, b) cout << a << " " <<  b << endl;
#define dbg3(a, b, c) cout << a << " " << b << " " << c << endl;
#define pb(x) push_back(x)
#define eb(x) emplace_back(x)
#define all(x) x.begin(), x.end()
#define f first
#define s second
#define lc p<<1
#define rc p<<1|1
using namespace std;
typedef long long LL;
typedef priority_queue<int, vector<int>, greater<int>> S_HEAP;
typedef priority_queue<int> B_HEAP; 
typedef pair<string, int> PSI;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
const int N = 1e5 + 10;


LL f(LL n, LL p) {
	if (n == 0) return 0;
	n /= p;
	return n + f(n, p);
}

int main() {
	LL k;
	cin >> k;

	vector<PLL> v1;
	LL x = k;

	for (LL i = 2; i * i <= x; i ++) {
		if (x % i) continue;
		int cnt = 0;
		while (x % i == 0) {
			x /= i;
			cnt ++;
		}
		v1.push_back({i, cnt});
	}

	if (x != 1) v1.push_back({x, 1});
	
	LL r1 = k, l1 = 0;

	while (l1 < r1) {
		LL mid = l1 + r1 >> 1;	
		bool ok = true;	
		for (auto x: v1) {
			if (f(mid, x.f) < x.s) ok = false;	
		}
		if (ok) r1 = mid;
		else l1 = mid + 1;
	}

	cout << l1 << endl;
}
posted on 2022-12-04 13:21  Jack404  阅读(79)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3