题目描述
白浅妹妹今天学习了求余运算,她很好奇求余运算和乘法运算结合起来会是什么样子,于是她设计了这样一道题目。
给定数字 n n n,你可以任选一个数字 k k k( 1 ≤ k ≤ n 1 \leq k \leq n 1≤k≤n),然后计算出 n % k n\%k n%k 的值(其中 % \% % 为求余运算),记为 q q q,请问 k × q k \times q k×q 的最大值是多少。
输入格式
输入仅包含一个正整数 n n n。
输出格式
输出仅一行,一个整数表示答案。
样例
样例输入
4
样例输出
3
数据范围与提示
样例说明:选择 k = 3 k = 3 k=3,那么用 4 4 4 求余 3 3 3 得到余数 1 1 1,最终算出答案为 1 × 3 = 3 1 \times 3 = 3 1×3=3。
测试点 1 − 5 1-5 1−5: n ≤ 1000 n \leq 1000 n≤1000
测试点 6 − 7 6-7 6−7: n ≤ 1 0 6 n \leq 10^6 n≤106
测试点 8 − 10 8 − 10 8−10: n ≤ 2 × 1 0 9 n \leq 2 \times 10^9 n≤2×109
思路及部分实现
上来先写个暴力,然后看着 n ≤ 2 × 1 0 9 n \leq 2 \times 10^9 n≤2×109 微妙的数据范围陷入沉思 … \dots … … \dots …
long long maxn=0;
for(int i=2;i<n;i++)
maxn=max(maxn,n%i*i);
printf("%lld",maxn);
试图强行优化结果 70 70 70 分,彻底疯狂。
long long maxn=0;
for(int i=2,j=n-1;j-i>=0;i++,j--)
maxn=max(maxn,max(n%i*i,n%j*j));
printf("%lld",maxn);
这大抵是道数学题吧。
模拟输出了一下,看到显示框的一瞬间我直接就汗毛耸立了,不知道读者有没有同感。
n = 20 ;
i = 1 , 20 % 1 * 1 = 0
i = 2 , 20 % 2 * 2 = 0
i = 3 , 20 % 3 * 3 = 6
i = 4 , 20 % 4 * 4 = 0
i = 5 , 20 % 5 * 5 = 0
i = 6 , 20 % 6 * 6 = 12
i = 7 , 20 % 7 * 7 = 42
i = 8 , 20 % 8 * 8 = 32
i = 9 , 20 % 9 * 9 = 18
i = 10 , 20 % 10 * 10 = 0
i = 11 , 20 % 11 * 11 = 99
i = 12 , 20 % 12 * 12 = 96
i = 13 , 20 % 13 * 13 = 91
i = 14 , 20 % 14 * 14 = 84
i = 15 , 20 % 15 * 15 = 75
i = 16 , 20 % 16 * 16 = 64
i = 17 , 20 % 17 * 17 = 51
i = 18 , 20 % 18 * 18 = 36
i = 19 , 20 % 19 * 19 = 19
i = 20 , 20 % 20 * 20 = 0
maxn = 99 ( i = 11 ) ;
答案不正不好就在中间的位置,且最大值的上一个数字与最大值相比突然相差很多, i i i 继续增加后运算的结果又越来越小,换了好几次输入都是如此,显然不是巧合,开始思考数学问题。
题目要求 k × q k \times q k×q 的最大值,我们先解决如何让 q q q( n % k n \% k n%k)的值最大。注意,以下推导过程中使用的变量含义均为在 a % b = c a \% b=c a%b=c 这个式子中的含义。先试着把中间值当作界限分为两部分进行分类讨论:
- 当 b > 1 2 a b > \frac{1}{2}a b>21a 时,由于两者的商不可能大于等于 2 2 2,则 a = b + c a=b+c a=b+c,这时要想使 c c c 的值最大,只需让 b b b 的值最小,因此 b = 1 2 a + 1 b=\frac{1}{2}a+1 b=21a+1
- 当 b = 1 2 a b = \frac{1}{2}a b=21a 时,运算结果必定为 0 0 0,因此不做考虑
- 当 b < 1 2 a b < \frac{1}{2}a b<21a 时,两者的商至少为 2 2 2,运算结果不可能大于 b > 1 2 a b > \frac{1}{2}a b>21a 的情况,同样不做考虑
解决了 q q q 的最大值的同时也确定了 k k k(即 b b b),题目到这里也就基本结束。代码实现如下:
long long ans=n%(n/2+1)*(n/2+1);
//不管奇偶性如何,k都取n/2+1,比如 4取3,5同样取3
完整代码
#include<iostream>
using namespace std;
int main(){
long long n;
scanf("%lld",&n);
long long ans=n%(n/2+1)*(n/2+1);
printf("%lld",ans);
return 0;
}