码蹄集 - MT3111· 赋值
Posted Tisfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了码蹄集 - MT3111· 赋值相关的知识,希望对你有一定的参考价值。
传送门
赋值
时间限制:1秒
空间限制:64M
题目描述
冒险团正在一座奇妙秘境探险,眼前正是秘境的奖励关,关卡机制如下:随机给定M个金币,如果能找到三个不大于M的正整数(可以相同),求得它们的最小公倍数S,那么冒险团就可以获得S枚金币。为了得到最多的金币,大家一致决定将这项求解任务交给你这位团队智囊,求出S的最大值。
输入描述
输入一个正整数n
- 1<=n<=1e6
输出描述
输出题意中三个数的最小公倍数S的最大值
样例一
输入
10
输出
630
题目分析
这道题题目可以概括为:求从 1 ∼ n 1\\sim n 1∼n中任选出三个数的最小公倍数的最大值。
这道题其实就是数学问题。想要暴力地枚举三个数的复杂度是 O ( n 3 ) O(n^3) O(n3),肯定会超时。
所以我们就需要用到互质的数学性质。以下结论可能未证明,但是不影响通过本题。
很明显,当三个数互质的时候,三个数的最小公倍数最大。
方法一:数学公式
- n n n为奇数时, n n n、 n − 1 n-1 n−1、 n − 2 n-2 n−2互质
- n n n为偶数时
- n n n能被 3 3 3整除时, n − 1 n-1 n−1、 n − 2 n-2 n−2、 n − 3 n-3 n−3互质
- n n n不能被 3 3 3整除时, n n n、 n − 1 n-1 n−1、 n − 3 n-3 n−3互质
有人可能不服气,为什么又上面这几条性质。这里感兴趣的同学可以去搜一搜,但是本文不在此做出证明,因为还有方法二。
方法二:局部暴力
真正遇到这样的题,不知道方法一的数学公式怎么办?
没关系,贪心也能过。
首先想要乘机尽可能大,我们就要把这三个数取得尽可能大。
所以我们可以在 n n n的附近进行贪心。本题时间限制是 1 s 1s 1s,在这 1 s 1s 1s的时间里,进行 1 0 6 10^6 106的计算量不过分吧!
我们只需要在 [ max ( 1 , n − 100 ) , n ] [\\max(1, n - 100), n] [max(1,n−100),n]的范围内枚举 i , j , k i,j,k i,j,k,即可在 1 0 6 10^6 106级别的运算量中得到最优答案。
方法三:公式+无脑
方法二是无脑计算法,之所以采用方法二是因为“不知道方法一的数学公式”。其实我们只需要在 [ max ( 1 , n − 3 ) , n ] [\\max(1, n - 3), n] [max(1,n−3),n]的范围内枚举三个数即可得到最优答案。(暂且记为方法三:公式+无脑)
AC代码
方法一:数学公式
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int main()
ll n;
cin >> n;
if (n % 2)
cout << n * (n - 1) * (n - 2) << endl;
else
if (n % 3 == 0)
cout << (n - 1) * (n - 2) * (n - 3) << endl;
else
cout << n * (n - 1) * (n - 3) << endl;
return 0;
方法二:局部暴力
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int main()
ll n;
cin >> n;
ll ans = 0;
for (ll i = max(1ll, n - 100); i <= n; i++)
for (ll j = max(1ll, n - 100); j <= n; j++)
for (ll k = max(1ll, n - 100); k <= n; k++)
/* // Error! 注释中是错误的求法 400 400 401的gcd为1,400*400*401/1/1 != 400 * 401
ll gcd = __gcd(__gcd(i, j), k);
ans = max(ans, i * j * k / gcd / gcd);
printf("i = %lld, j = %lld, k = %lld, __gcd(i, j, k) = %lld, GBS = %lld\\n", i, j, k, gcd, i * j * k / gcd / gcd);
*/
ll thisAns = i * j / __gcd(i, j);
thisAns = thisAns * k / __gcd(thisAns, k);
ans = max(ans, thisAns);
cout << ans << endl;
return 0;
方法三:公式+无脑
运行时间大大缩短
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int main()
ll n;
cin >> n;
ll ans = 0;
for (ll i = max(1ll, n - 3); i <= n; i++)
for (ll j = max(1ll, n - 3); j <= n; j++)
for (ll k = max(1ll, n - 3); k <= n; k++)
ll thisAns = i * j / __gcd(i, j);
thisAns = thisAns * k / __gcd(thisAns, k);
ans = max(ans, thisAns);
cout << ans << endl;
return 0;
每周提前更新菁英班周赛题解,点关注,不迷路
原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/125538415
以上是关于码蹄集 - MT3111· 赋值的主要内容,如果未能解决你的问题,请参考以下文章