CF#538(div 2) C. Trailing Loves (or L'oeufs?) 【经典数论 n!的素因子分解】

本文详细解析了Codeforces C. TrailingLoves问题,介绍了如何求解n!在b进制下末尾零的数量,通过素数分解和累除法计算素因子的幂,最终确定最大整数k使n!%(b^k)==0。提供了完整的AC代码和解题思路。

任意门:http://codeforces.com/contest/1114/problem/C

C. Trailing Loves (or L'oeufs?)

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
The number "zero" is called "love" (or "l'oeuf" to be precise, literally means "egg" in French), for example when denoting the zero score in a game of tennis.

Aki is fond of numbers, especially those with trailing zeros. For example, the number 92009200 has two trailing zeros. Aki thinks the more trailing zero digits a number has, the prettier it is.

However, Aki believes, that the number of trailing zeros of a number is not static, but depends on the base (radix) it is represented in. Thus, he considers a few scenarios with some numbers and bases. And now, since the numbers he used become quite bizarre, he asks you to help him to calculate the beauty of these numbers.

Given two integers nn and bb (in decimal notation), your task is to calculate the number of trailing zero digits in the bb-ary (in the base/radix of bb) representation of n!n! (factorial of nn).

Input

The only line of the input contains two integers nn and bb (1n10181≤n≤1018, 2b10122≤b≤1012).

Output

Print an only integer — the number of trailing zero digits in the bb-ary representation of n!n!

Examples
input
Copy
6 9
output
Copy
1
input
Copy
38 11
output
Copy
3
input
Copy
5 2
output
Copy
3
input
Copy
5 10
output
Copy
1
Note

In the first example, 6!(10)=720(10)=880(9)6!(10)=720(10)=880(9).

In the third and fourth example, 5!(10)=120(10)=1111000(2)5!(10)=120(10)=1111000(2).

The representation of the number xx in the bb-ary base is d1,d2,,dkd1,d2,…,dk if x=d1bk1+d2bk2++dkb0x=d1bk−1+d2bk−2+…+dkb0, where didi are integers and 0dib10≤di≤b−1. For example, the number 720720 from the first example is represented as 880(9)880(9) since 720=892+89+01720=8⋅92+8⋅9+0⋅1.

You can read more about bases here.

 

题意概括:

求 n! 转化为 b 进制下末尾有多少个 0.

 

解题思路:

原题:swjtuOJ 2090

这是一道很好的数论题。

首先转换一下思路:

要求 n! 在 b 进制下有多少个尾 0 就相当于 求 n! % (b^k) == 0 的最大 k。

那么我们现在把 n! 看作一个数 A。问题就是 求 A % (b^k) == 0 的最大 k;

我们知道有素数分解定理: b = p1^a1 * p2^a2 * p3^a3 ...;

那么我们如果可以求得 A 里面 p1^b1 * p2^b2 * p3^b3 ...  的 b1, b2, b3...

那么答案 ans = min(ans, ai/bi ) 了也就是要整除,首先要满足最小的那个能整除。

 

(1)首先对 b 进行素因子分解,直接暴力(log b), 用一个数组离散化形成该素因子的编号和该素因子的幂的映射 或者 用map存储该素因子的幂,得到所有素因子以及素因子的幂 

(2)对于每一个素因子p,计算对应的 A(即 n! ) 中素因子p的幂,两者相除取所有p幂的最小值就是对应的最大整数。

 

这里求 n! 下 素因子 p 的幂 用累除法,因为存在推论:

n! 下 p 的幂 = [ n/p ] + [ n/(p^2) ] + [ n/(p^3) ]  ...

 

学习:

https://blog.youkuaiyun.com/Wen_Yongqi/article/details/86976902

 

AC code:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<vector>
 6 #include<queue>
 7 #include<cmath>
 8 #include<set>
 9 #include<map>
10 #define INF 0x3f3f3f3f
11 #define LL long long
12 using namespace std;
13 const int MAXN = 2e6+1000;
14 LL N, B;
15 vector<LL>prime;
16 //LL num[MAXN];
17 map<LL, int>mmp;
18 void get_p(LL n)
19 {
20     LL len = sqrt((double)n);
21     //printf("len %lld\n", len);
22     for(LL i = 2; i <= len; i++){
23         if(n%i == 0){
24             prime.push_back(i);
25             while(n%i == 0){
26                 n/=i;
27                 //num[prime.size()-1]++;
28                 mmp[i]++;
29             }
30         }
31     }
32     if(n != 1){
33         prime.push_back(n);
34 //        num[prime.size()-1]++;
35         mmp[n]++;
36     }
37 }
38 
39 LL calc(LL n, LL p)
40 {
41     LL res = 0;
42     while(n){
43         res += n/p;
44         n/=p;
45         //puts("zjy");
46     }
47     return res;
48 }
49 
50 int main()
51 {
52     LL sum = 1LL;
53     scanf("%I64d %I64d", &N, &B);
54     get_p(B);
55     LL ans = (1LL<<62);
56     for(LL i = 0; i < prime.size(); i++){
57 //        ans = min(ans, calc(N, prime[i])/num[i]);
58         //puts("zjy");
59         ans = min(ans, calc(N, prime[i])/mmp[prime[i]]);
60     }
61 
62     printf("%I64d\n", ans);
63     return 0;
64 }

 

private lazy var scrollView: DeviceListMasterMultiResponseScrollView = { guard !showLocalDeviceOnly else { return DeviceListMasterMultiResponseScrollView() } let top: CGFloat = navigationController?.navigationBar.frame.maxY ?? 0 let bottom: CGFloat = self.tabBarController?.tabBar.bounds.height ?? 0 let screenWidth = UIScreen.main.bounds.width let scrollView = DeviceListMasterMultiResponseScrollView(frame: CGRect(x: 0, y: top, width: screenWidth, height: screenHeight - top - bottom)) scrollView.bounces = false scrollView.isScrollEnabled = true scrollView.showsVerticalScrollIndicator = false scrollView.delegate = self scrollView.backgroundColor = .clear scrollView.contentInset = UIEdgeInsets.zero scrollView.contentSize = CGSize(width: scrollView.frame.width, height: scrollView.frame.height + nameLabelViewHeight + 62) scrollView.addSubview(scrollViewContainerView) return scrollView }() override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate(alongsideTransition: { _ in let newScreenWidth = UIScreen.main.bounds.width self.scrollView.frame = CGRect( x: 0, y: self.navigationController?.navigationBar.frame.maxY ?? 0, width: newScreenWidth, height: UIScreen.main.bounds.height - (self.navigationController?.navigationBar.frame.maxY ?? 0) - (self.tabBarController?.tabBar.bounds.height ?? 0) ) self.scrollView.contentSize = CGSize( width: newScreenWidth, height: self.scrollView.frame.height + self.nameLabelViewHeight + 62 ) }, completion: nil) } private lazy var scrollViewContainerView: UIView = { guard !showLocalDeviceOnly else { return UIView() } if tabBarContainerTopConstraint != nil { tabBarContainerTopConstraint.constant = nameLabelViewHeight } let top: CGFloat = navigationController?.navigationBar.frame.maxY ?? 0 let bottom: CGFloat = self.tabBarController?.tabBar.bounds.height ?? 0 let scrollViewContainerView = UIView(frame: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight - top - bottom)) scrollViewContainerView.backgroundColor = .clear scrollViewContainerView.addSubview(headerSearchView) scrollViewContainerView.addSubviews([tabBarContainer]) headerSearchView.snp.makeConstraints { make in make.top.equalToSuperview().offset(10) make.height.equalTo(62) make.leading.trailing.equalToSuperview() } tabBarContainer.snp.makeConstraints({make in make.top.equalTo(headerSearchView.snp.bottom) make.height.equalTo(tabCollectionHeightConstant.constant) make.leading.equalToSuperview() make.trailing.equalToSuperview() }) return scrollViewContainerView }() 现在是这样
最新发布
10-21
你现在的代码结构已经非常清晰,`scrollView` 和 `scrollViewContainerView` 都是通过 `lazy var` 初始化的,并且在屏幕旋转时通过 `viewWillTransition(to:with:)` 方法动态更新了 `scrollView` 的 frame 和 contentSize。 不过,有几个潜在问题需要注意和优化: --- ### ✅ 1. **关于 `screenWidth` 和 `screenHeight` 的使用** 你在 `scrollViewContainerView` 的初始化中使用了未定义的变量 `screenWidth` 和 `screenHeight`,这会导致编译错误。你需要将它们替换为实际值,比如: ```swift let screenWidth = UIScreen.main.bounds.width let screenHeight = UIScreen.main.bounds.height ``` --- ### ✅ 2. **关于 `tabBarContainerTopConstraint` 的使用** 你在 `scrollViewContainerView` 中使用了 `if tabBarContainerTopConstraint != nil { ... }`,但此时 `tabBarContainerTopConstraint` 可能还未被赋值或设置,因此这个判断可能无效。建议将其移到视图加载完成后(如 `viewDidLoad`)进行设置。 --- ### ✅ 3. **关于 Auto Layout 和 Frame 混合使用的问题** 你混合使用了 `frame` 和 `SnapKit` 的约束布局方式。虽然这是可以接受的,但在屏幕旋转时可能会导致布局不一致。如果你使用了 SnapKit 约束,建议不要手动设置 `frame`,而是通过重新计算约束来实现响应式布局。 --- ### ✅ 4. **`scrollView.contentSize` 的更新时机** 你目前在 `viewWillTransition(to:with:)` 中更新了 `scrollView.contentSize`,但如果内容高度依赖于其他 UI 元素(例如 `nameLabelViewHeight`),建议确保这些值在旋转时也同步更新。 --- ### ✅ 5. **代码示例优化后的版本** ```swift private lazy var scrollView: DeviceListMasterMultiResponseScrollView = { guard !showLocalDeviceOnly else { return DeviceListMasterMultiResponseScrollView() } let top: CGFloat = navigationController?.navigationBar.frame.maxY ?? 0 let bottom: CGFloat = self.tabBarController?.tabBar.bounds.height ?? 0 let screenWidth = UIScreen.main.bounds.width let screenHeight = UIScreen.main.bounds.height let scrollView = DeviceListMasterMultiResponseScrollView(frame: CGRect(x: 0, y: top, width: screenWidth, height: screenHeight - top - bottom)) scrollView.bounces = false scrollView.isScrollEnabled = true scrollView.showsVerticalScrollIndicator = false scrollView.delegate = self scrollView.backgroundColor = .clear scrollView.contentInset = UIEdgeInsets.zero scrollView.contentSize = CGSize(width: scrollView.frame.width, height: scrollView.frame.height + nameLabelViewHeight + 62) scrollView.addSubview(scrollViewContainerView) return scrollView }() override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate(alongsideTransition: { _ in let newScreenWidth = UIScreen.main.bounds.width self.scrollView.frame = CGRect( x: 0, y: self.navigationController?.navigationBar.frame.maxY ?? 0, width: newScreenWidth, height: UIScreen.main.bounds.height - (self.navigationController?.navigationBar.frame.maxY ?? 0) - (self.tabBarController?.tabBar.bounds.height ?? 0) ) self.scrollView.contentSize = CGSize( width: newScreenWidth, height: self.scrollView.frame.height + self.nameLabelViewHeight + 62 ) }, completion: nil) } private lazy var scrollViewContainerView: UIView = { guard !showLocalDeviceOnly else { return UIView() } let top: CGFloat = navigationController?.navigationBar.frame.maxY ?? 0 let bottom: CGFloat = self.tabBarController?.tabBar.bounds.height ?? 0 let screenWidth = UIScreen.main.bounds.width let screenHeight = UIScreen.main.bounds.height let scrollViewContainerView = UIView(frame: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight - top - bottom)) scrollViewContainerView.backgroundColor = .clear scrollViewContainerView.addSubview(headerSearchView) scrollViewContainerView.addSubviews([tabBarContainer]) headerSearchView.snp.makeConstraints { make in make.top.equalToSuperview().offset(10) make.height.equalTo(62) make.leading.trailing.equalToSuperview() } tabBarContainer.snp.makeConstraints({make in make.top.equalTo(headerSearchView.snp.bottom) make.height.equalTo(tabCollectionHeightConstant.constant) make.leading.equalToSuperview() make.trailing.equalToSuperview() }) return scrollViewContainerView }() ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值