目录
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
小红来到了一家蛋糕店,蛋糕店中售卖了若干种不同的长方体蛋糕,具体来讲,蛋糕店中售卖若干种形状为横向长度不大于nnn,纵向长度不大于mmm,高度不大于ppp个单位的蛋糕。每个蛋糕的表面要裹上奶油,也就是说,除了底面以外,其余5个面都需要裹奶油。我们不妨定义:奶油消耗量为暴露在空气中的5个面的面积之和。
我们定义两种蛋糕是不同的,当且仅当两个蛋糕的横向或者纵向长度或高度不同。即分别定义蛋糕横向的长度为iii,纵向的长度为jjj,高度为kkk,则可以用三元组(i,j,k)(i,j,k)(i,j,k)表示蛋糕种类的唯一性。
现在小红希望你求出,共有多少种不同的奶油消耗量为xxx的蛋糕?
输入描述:
第一行输入四个正整数n,m,p,xn,m,p,xn,m,p,x,用空格隔开。 1≤n,m,p≤30001\leq n,m,p \leq 30001≤n,m,p≤3000 1≤x≤1071\leq x \leq 10^71≤x≤107
输出描述:
消耗量为xxx的蛋糕的种类数。
示例1
输入
2 2 2 8
输出
2
说明
如下图,共有以下两种蛋糕的奶油消耗量为8。
思路
我直接疯狂之暴力
一开始肯定是直接三层for循环遍历三条边的全部长度获取全部的可能来写出这道题嘛。直接暴力的代码如下:
代码实现
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
// 横向长度
int n = sc.nextInt();
// 纵向长度
int m = sc.nextInt();
// 高度
int p = sc.nextInt();
// 面积
int x = sc.nextInt();
int res = 0;
// 横向
for (int i = 1; i <= n; i++) {
// 纵向
for (int j = 1; j <= m; j++) {
// 高度
for(int k = 1; k <= p; k++){
// 判断面积是否为x
if(2*i*k+2*j*k+j*k == x){
res++;
}
}
}
}
System.out.println(res);
}
}
但是这种我试过了,给你的测试用例当然是对的,但是只能通过20%的题目,其他的测试用例AC不了。因为他的 ,3000*3000*3000是多少,所以这个时间复杂度为
的算法过不了一点。
我是大聪明之我爱数学
有没有一个方法可以降低一层或者两层for循环呢?
答案当然是存在的,我们来思考,n,m,p分别是横向,纵向和高度,x的面积可以由它们表示如下公式:
那么如果我们想降低一层for循环,是不是就需要将其中一个未知量用其他的来代替,让他只有两个未知量,那我们可以提取一下 2p得到如下的公式:
是不是就可以把p的表达式求解出来如下公式:
但是你如果把这个p带进原式你就会发现上面都没干,变成了x=x,那我们求解出这个答案干嘛。
重点来了,这里我们得到了p的答案,x是固定的,那么 n和m我们可以使用两层for来遍历寻找,然后是不是就可以每次找到一个 p ,我们直接判断这个p是不是在题目中给的p的范围不就完美解决了吗?哈哈哈哈哈哈拿下!!!
但是还是有坑,因为语言的问题,你之前输入的都是整数,如果遇到例如 ,这种情况如果还恰好满足你的范围,那就出事了,所以我们应该排除小数的情况,只保留答案刚好是整数的情况,因此我们还需要增添一个 p 是整数的判断。
代码实现:
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
// 横向长度
int n = sc.nextInt();
// 纵向长度
int m = sc.nextInt();
// 高度
int p = sc.nextInt();
// 面积
int x = sc.nextInt();
int res = 0;
// 横向
for (int i = 1; i <= n; i++) {
// 纵向
for (int j = 1; j <= m; j++) {
// 高度
double k = (x - i*j)*1.0/(2*(i+j));
// 判断是否为整数且在范围中
if( k % 1 == 0 && k <= p && k > 0) {
res++;
}
}
}
System.out.println(res);
}
}
那么你就可以拿下这道题喽!!!!
总结
这道题如果是蓝桥杯的题目的话,恭喜你暴力至少可以过两个测试用例,但是牛客周赛是ACM赛制,所以你还是需要降低代码的时间复杂度,我们这里使用了一个数学的思维来解决这道题。所有的通过数学思路解决的题目都有一个通病就是,只要你想到了这道题的数学原理那么这道题就会变得无比简单,因为代码很好实现,就是数学的逻辑难想到罢辽~~~~~
大家如果喜欢,点个赞呗,谢谢啦Thanks♪(・ω・)ノ