题目链接:https://ac.nowcoder.com/acm/contest/6776
牛牛有一个边长为1的正六边形,只要牛牛一推它就可以一直滚下去,正六边形左下角为A,牛牛想知道正六边形翻滚k次A点的轨迹边长是多少呢。如图是正六边形翻滚一次的情况。给定正六边形翻滚次数k,求A点翻滚轨迹长度
输入 | 3 |
输出 | 4.955392 |
备注 | 1 <= k <= 10^3,返回值与答案误差应小于0.00001 |
模拟的题目。每次旋转60度,只要知道每次转的扇形的边长即可。有6次,每次的边长是{ 1, 根号3, 2, 根号3, 1, 0 },完了根据边累和长度,累和再乘以π/3.
π的计算可以用下面的式子来写:acos(-1.0), 或者atan(1.0) * 4.
#include
class Solution {
public:
/**
*
* @param k int整型 翻滚次数
* @return double浮点型
*/
double circumference(int k) {
double a[6] = {1.0, sqrt(3.0), 2.0, sqrt(3.0), 1.0, 0};
double ans = 0;
for (int i = 0; i < k; i++) {
ans += a[i % 6];
}
return acos(-1.0) / 3 * ans;
}
};
在牛牛面前有nnn个瓶子,每个瓶子的大小体积都一样,但是每个瓶子内的含水量都不相同。
因为牛牛是个完美主义者,他希望瓶子中的水能够满足他的要求,他的要求是瓶子中的水最少为x。所以他打算对这些瓶子里的水进行重新分配,以满足最多的瓶子中水量大于等于x。
牛牛的分配规则是:每次可以选择多个瓶子,将里面的水平均分配到已选择的瓶子中。
给定n个瓶子和牛牛的对瓶中的水量要求x,以及n个瓶子中的含水量,求最多可以有多少个瓶子满足牛牛的要求?
从大到小对瓶子里的水量进行排序,然后每选一个瓶子,就平均一下看看平均水量是否大于x,如果是则继续,如果不是就直接break。返回最大的瓶子数。(我为什么就没想到呢?)。因为,如果你再选择比水量比这个瓶子小的,平均水量更低了,所以这个从大到小得到的值是最大的值。
typedef long long LL;
class Solution {
public:
/**
* 返回重新分配后,满足牛牛要求的水量的瓶子最多的数量
* @param n int整型 瓶子的数量
* @param x int整型 牛牛的对瓶中的水量要求
* @param a int整型vector 每个瓶子中的含水量
* @return int整型
*/
int solve(int n, int x, vector& a) {
sort(a.begin(), a.end());
int ans = 0;
LL sum = 0;
for (int i = n - 1; i >= 0; i--) {
sum += a[i];
if (sum >= 1LL * (n - i) * x) { //1.为了避免除不尽有精度问题,我们把除换成了乘。
ans = n - i; //2.并且加上LL类型,防止数据溢出。
}
}
return ans;
}
};
牛牛和牛妹在玩一个游戏,在他们面前有n个数,他们对每个数可以进行 +1 或 -1 操作,但对于每一个数,该操作最多只能执行一次。
游戏胜利的目标是:使用最少的操作次数,将这几个数构造成一个等差数列。
牛牛特别想赢得游戏,所以他想让你帮他写一个程序,得出最少多少次操作后能使这几个数变成一个等差数列,当然,如果完全不能构造成功,就输出-1。
讲解者说她的第一想法是用DP,结果发现不合适。然后想到了枚举。共枚举9种状态。由于确定一个等差数列只需要知道首项和等差即可。我们先确定前两项,然后判断后面是否合适即可。共枚举9中状态。a[0], a[0] + 1, a[0] - 1. b[0], b[0] + 1, b[0] - 1.共3*3 = 9种,确定首项和等差,然后判断后面的值每一步是否满足值的绝对值最多相差1.如果是,cnt累计起来,然后最终如果找到了结果,就返回一个最小的结果即可。
#include
class Solution {
public:
/**
* 返回最少多少次操作后能使这几个数变成一个等差数列,如果完全不能构造成功,就返回-1
* @param n int整型 代表一共有n个数字
* @param b int整型vector 代表这n个数字的大小
* @return int整型
*/
int solve(int n, vector& b) {
// write code here
if (n <= 2) return 0; //等差数列本身就是由2个数就可以确定。
int ans = 0x7fffffff;
for (int i = -1; i <= 1; i++) //判断a[0]加上-1, 0, 1的情况
for (int j = -1; j <= 1; j++) { //判断a[1] 加上-1,0,1的情况。
int fst = b[0] + i; //首项
int scd = b[1] + j; //第二项。
int delta = fst - scd; //等差
int cur = scd; //表示当前值
int cnt = abs(i) + abs(j);//cnt表示变成等差数列需要多少次变换。初始值为第1位和第2位变换的次数。
for (int x = 2; x < n; x++) {
cur -= delta; //当前值减去等差后与下一项作比较。
if (abs(cur - b[x]) <= 1) { //如果原来的值最多加1,减1或者值相同则累计这种情况
cnt += abs(cur - b[x]);
} else {
break;
}
if (x == n - 1) {
ans = min(ans, cnt); //比较获取最大值
}
}
}
if (ans < 0x7fffffff) return ans;
return -1;
}
};