目录
翻滚吧牛牛(一)
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
牛牛有一个边长为1的正六边形,只要牛牛一推它就可以一直滚下去,正六边形左下角为A,牛牛想知道正六边形翻滚k次A点的轨迹边长是多少呢。如图是正六边形翻滚一次的情况。给定正六边形翻滚次数k,求A点翻滚轨迹长度
示例1
输入
3
输出
4.955392
备注:
1≤k≤1031\leq k\le10^31≤k≤103,返回值与答案误差应小于0.00001
思路:
class Solution {
public:
/**
*
* @param k int整型 翻滚次数
* @return double浮点型
*/
double circumference(int k) {
// write code here
double num[6] = {0,2.0,2*sqrt(3),4.0,2*sqrt(3),2.0};
double ans = 0;
for(int i=1; i<=k; i++)
ans += num[i % 6];
return ans * acos(-1) / 6;
}
};
牛牛的分配
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
在牛牛面前有nnn个瓶子,每个瓶子的大小体积都一样,但是每个瓶子内的含水量都不相同。
因为牛牛是个完美主义者,他希望瓶子中的水能够满足他的要求,他的要求是瓶子中的水最少为xxx。所以他打算对这些瓶子里的水进行重新分配,以满足最多的瓶子中水量大于等于xxx。
牛牛的分配规则是:每次可以选择多个瓶子,将里面的水平均分配到已选择的瓶子中。
给定nnn个瓶子和牛牛的对瓶中的水量要求xxx,以及nnn个瓶子中的含水量,求最多可以有多少个瓶子满足牛牛的要求?
示例1
输入
3,7,[9,4,9]
输出
3
说明
一共有3瓶水,容量分别为9 4 9,牛牛希望每瓶水中最少容量为7。所以可以选择这3瓶水,平均分配后每瓶水的含量都大于7,所以满足牛牛要求的瓶子最多的数量为3。
示例2
输入
2,5,[4,3]
输出
0
说明
一共有2瓶水,但是每瓶水的容量都无法满足牛牛的要求,所以即使不管怎么分配,也无法满足牛牛的要求。
备注:
1≤n≤106,代表瓶子的数量1 \leq n \leq 10^{6},代表瓶子的数量1≤n≤106,代表瓶子的数量
1≤x≤109,代表牛牛的对瓶中的水量要求1 \leq x \leq 10^{9},代表牛牛的对瓶中的水量要求1≤x≤109,代表牛牛的对瓶中的水量要求
a1,a2,a3...an(1≤ai≤109)代表每个瓶子中的含水量a_{1},a_{2},a_{3}...a_{n}(1 \leq a_{i} \leq 10^{9})代表每个瓶子中的含水量a1,a2,a3...an(1≤ai≤109)代表每个瓶子中的含水量
对于25%的数据,1≤n≤102,1≤x,ai≤103对于25\%的数据,1 \leq n \leq 10^{2},1 \leq x,a_{i} \leq 10^{3}对于25%的数据,1≤n≤102,1≤x,ai≤103
对于75%的数据,1≤n≤104,1≤x,ai≤106对于75\%的数据,1 \leq n \leq 10^{4},1 \leq x,a_{i} \leq 10^{6}对于75%的数据,1≤n≤104,1≤x,ai≤106
对于100%的数据,1≤n≤106,1≤x,ai≤109对于100\%的数据,1 \leq n \leq 10^{6},1 \leq x,a_{i} \leq 10^{9}对于100%的数据,1≤n≤106,1≤x,ai≤109
思路:从大到小排序,取前i个平均值,小于x则不可能继续。
class Solution {
public:
/**
* 返回重新分配后,满足牛牛要求的水量的瓶子最多的数量
* @param n int整型 瓶子的数量
* @param x int整型 牛牛的对瓶中的水量要求
* @param a int整型vector 每个瓶子中的含水量
* @return int整型
*/
int solve(int n, int x, vector<int>& a) {
// write code here
sort(a.begin(), a.end(),greater<int>());
long long sum = 0;
int ans = 0;
for(int i=0; i<n; i++){
sum+=a[i];
if(sum / (i+1) < x) break;
ans++;
}
return ans;
}
};
牛牛构造等差数列
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
牛牛和牛妹在玩一个游戏,在他们面前有n个数,他们对每个数可以进行 +1 或 -1 操作,但对于每一个数,该操作最多只能执行一次。
游戏胜利的目标是:使用最少的操作次数,将这几个数构造成一个等差数列。
牛牛特别想赢得游戏,所以他想让你帮他写一个程序,得出最少多少次操作后能使这几个数变成一个等差数列,当然,如果完全不能构造成功,就输出-1。
示例1
输入
4,[24,21,14,10]
输出
3
说明
在第一个例子中,牛牛应该对第一个数字+1,对第二个数字-1,对第三个数字+1,而第四个数字应该保持不变。最后,序列就变成了[25,20,15,10],这是一个等差数列且操作次数最少。
示例2
输入
3,[14,5,1]
输出
-1
说明
在第二个例子中,不可能只对其中的数字最多操作一次就得到等差数列。
备注:
1≤n≤105,代表有n个数1\leq n \leq10^{5},代表有n个数1≤n≤105,代表有n个数
b1,b2,...bn(1≤bi≤109),代表这n个数字的大小b_{1},b_{2},...b_{n} (1\leq b_{i} \leq10^{9}),代表这n个数字的大小b1,b2,...bn(1≤bi≤109),代表这n个数字的大小
对于20%的数据,1≤n≤10,1≤bi≤103对于20\%的数据,1\leq n \leq10, 1\leq b_{i} \leq10^{3}对于20%的数据,1≤n≤10,1≤bi≤103
对于60%的数据,1≤n≤103,1≤bi≤106对于60\%的数据,1\leq n \leq10^{3}, 1\leq b_{i} \leq10^{6}对于60%的数据,1≤n≤103,1≤bi≤106
对于100%的数据,1≤n≤105,1≤bi≤109对于100\%的数据,1\leq n \leq10^{5}, 1\leq b_{i} \leq10^{9}对于100%的数据,1≤n≤105,1≤bi≤109
思路:本来以为是dp,听课以后居然是暴力模拟。根据前两个数求出d,对剩余数字进行判断即可。
class Solution {
public:
/**
* 返回最少多少次操作后能使这几个数变成一个等差数列,如果完全不能构造成功,就返回-1
* @param n int整型 代表一共有n个数字
* @param b int整型vector 代表这n个数字的大小
* @return int整型
*/
int solve(int n, vector<int>& b) {
// write code here
int ans = 0x3f3f3f3f;
for(int i=-1; i<=1; i++)
for(int j=-1; j<=1; j++){
int x = b[0] + i;
int y = b[1] + j;
int mul = y - x;
int cnt = abs(i) + abs(j);
int k;
int cur = y;
for(k=2; k<n; k++){
cur += mul;
if(abs(cur - b[k]) <= 1) cnt += abs(cur - b[k]);
else break;
}
if(k == n) ans = min(ans, cnt);
}
if(ans < 0x3f3f3f3f) return ans;
return -1;
}
};
playfair:
模拟,不知道playfair如何排列可自行百度。
牛牛摇骰子
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
牛牛非常擅长摇骰子,不管给他一个什么样的骰子他都能准确的掷出他想要的那一面。现在有一个四面体骰子,四个面分别是四个整数0,3,7,11。牛牛在玩一个游戏。牛牛初始在一个数轴的原点,每当他摇出一个数字x,他可以自行选择向左走x步或者向右走x步。牛牛想知道他最少摇多少次骰子可以从原点到达坐标为p的点。
现在一共有N次询问,请你返回从0点到询问的每一个坐标arr[i]所需要摇筛子的最小次数。
示例1
输入
[1,4,14]
输出
[3,2,2]
说明
从0到1最少需要摇3次骰子(0->7->4->1)(走法不唯一,比如0->11->4->1也只需要掷3次骰子)
从0到4最少需要摇2次骰子(0->7->4)
从0到14最少需要摇2次骰子(0->7->14)
示例2
输入
[6,25]
输出
[2,3]
说明
从0到6最少需要摇2次骰子(0->3->6)
从0到25最少需要摇3次骰子(0->7->18->25)
思路:明显0不会用,尽量多用11,但需要对余为2的情况进行特判,因为13 = 3 + 7 + 3,先走11的话会增加步数。
class Solution {
public:
/**
* 把所有询问的答案按询问顺序放入vector里
* @param arr int整型vector 要查询坐标的数组
* @return int整型vector
*/
vector<int> MinimumTimes(vector<int>& arr) {
// write code here
int steps[11] = {0,3,4,1,2,3,2,1,2,3,2};
vector<int > ans;
for(int i=0; i<arr.size(); i++){
if(arr[i] % 11 == 2 && arr[i] != 2) ans.push_back(2+arr[i]/11);
else ans.push_back(arr[i]/11 + steps[arr[i] % 11]);
}
return ans;
}
};
反复横跳
时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
题意
牛牛在某著名游戏公司接了一项任务,已知游戏中有n个点,任意两个点之间由具有一定长度的双向通道连接,并且任意两个点之间有且仅有一条路径使其可以相互到达。牛牛现在的任务为:需要在游戏中操控人物从任意一点作为起点出发,所有的点至少经过一次,可以在任意一点停止交付任务,请问牛牛最少需要操控人物走多远。
输入
第一个参数为 nnn,1≤n≤100,0001\leq n \leq 100,0001≤n≤100,000
第二个参数为大小为 n−1n-1n−1 的点对 (ui,vi)(u_i, v_i)(ui,vi) 的集合 EdgeEdgeEdge ,其中 (ui,vi)(u_i, v_i)(ui,vi) 表示结点 uiu_iui 与结点 viv_ivi 之间有一条边,1≤ui,vi≤n1\leq u_i, v_i \leq n1≤ui,vi≤n
第三个参数为大小为 n−1n-1n−1 的整数集合 fff ,其中 fif_ifi 表示第 iii 条边的长度,1≤fi≤100,0001\leq f_i \leq 100,0001≤fi≤100,000
输出
最短距离
示例1
输入
5,[(1,2),(2,3),(3,4),(2,5)],[39,48,54,100]
输出
280
说明
从 4 号点出发,路径为 4 - 3 - 2 - 1 - 2 - 5。
思路:树的直径以外的边都要走两遍。
/**
* struct Point {
* int x;
* int y;
* };
*/
typedef long long ll;
const int N = 100000 + 10;
int h[N],e[N*2],ne[N*2],idx=0,w[N*2];
int vis[N];
ll sum;
int point;
ll ans;
class Solution {
public:
/**
* 最短距离
* @param n int整型
* @param Edge Point类vector
* @param val int整型vector
* @return long长整型
*/
void add(int a, int b, int c){
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
void dfs(int u, int fa, int dis){
if(dis > ans){
ans = dis;
point = u;
}
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
if(j != fa){
dfs(j, u, dis+w[i]);
}
}
}
long long solve(int n, vector<Point>& Edge, vector<int>& val) {
memset(h, -1, sizeof h);
for(int i=0; i<n-1; i++){
int a = Edge[i].x;
int b = Edge[i].y;
int c = val[i];
sum += c;
add(a,b,c);
add(b,a,c);
}
sum*=2;
dfs(1,0,0);
dfs(point,0,0);
return sum-ans;
}
};