一、好数
题目描述
一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位 · · · )上的数字是奇数,偶数位(十位、千位、十万位 · · · )上的数字是偶数,我们就称之为“好数”。给定一个正整数 N,请计算从 1 到 N 一共有多少个好数。
输入格式
一个整数 N。
输出格式
一个整数代表答案。
样例输入
复制
24
样例输出
复制
7
提示
对于第一个样例,24 以内的好数有 1、3、5、7、9、21、23,一共 7 个
最终代码:
#include<bits/stdc++.h>
using namespace std;
//1 3 5 7 9 - >5
//2 4 6 8 0 - >5
//10->5 35 0->5 + 2->5 355 ->300,1*5*5 3 +3*5 + 5 3
//25+15
int main(){
int N;
cin>>N;
string odd = "13579";
string even = "02468";
int res = 0;
for(int i=0;i<=N;i++){
//TODO
string s = to_string(i);
bool flag = true;
for(int i=s.size()-1,j=s.size()-2;i>=0;i-=2,j-=2){
if((odd.find(s[i])==string::npos&&i>=0)||(even.find(s[j])==string::npos&&j>=0)){
flag = false;
break;
}
else{
continue;
}
}
if(flag){
res++;
}
}
cout<<res;
return 0;
}
二、R 格式
题目描述
小蓝最近在研究一种浮点数的表示方法:R 格式。对于一个大于 0 的浮点数 d,可以用 R 格式的整数来表示。给定一个转换参数 n,将浮点数转换为 R格式整数的做法是:
1. 将浮点数乘以 2n;
2. 四舍五入到最接近的整数。
输入格式
一行输入一个整数 n 和一个浮点数 d,分别表示转换参数,和待转换的浮点数。
输出格式
输出一行表示答案:d 用 R 格式表示出来的值。
样例输入
复制
2 3.14
样例输出
复制
13
提示
【样例说明】
3.14 × 22 = 12.56,四舍五入后为 13。
【评测用例规模与约定】
对于 50% 的评测用例:1 ≤ n ≤ 10,1 ≤ 将 d 视为字符串时的长度 ≤ 15。
对于 100% 的评测用例:1 ≤ n ≤ 1000,1 ≤ 将 d 视为字符串时的长度≤ 1024;保证 d 是小数,即包含小数点。
最终代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
int n;
string str;
vector<int> add(vector<int> A, vector<int> B)
{
vector<int> C;
for (int i = 0, t = 0; i < A.size() || i < B.size() || t; ++ i )
{
if (i < A.size())
t += A[i];
if (i < B.size())
t += B[i];
C.push_back(t % 10);
t /= 10;
}
return C;
}
int main()
{
cin >> n >> str;
int k = str.size() - 1;
while (str[k] != '.')
k --;
str.erase(k, 1);
k = str.size() - k;
vector<int> A;
for (int i = str.size() - 1; i >= 0; -- i )
A.push_back(str[i] - '0');
while (n -- )
A = add(A, A);
int p = A[k - 1];
reverse(A.begin(), A.end());
while (k -- )
A.pop_back();
reverse(A.begin(), A.end());
if (p >= 5)
A = add(A, {1});
for (int i = A.size() - 1; i >= 0; -- i )
cout << A[i];
return 0;
}
三、宝石组合
题目描述
在一个神秘的森林里,住着一个小精灵名叫小蓝。有一天,他偶然发现了一个隐藏在树洞里的宝藏,里面装满了闪烁着美丽光芒的宝石。这些宝石都有着不同的颜色和形状,但最引人注目的是它们各自独特的 “闪亮度” 属性。每颗宝石都有一个与生俱来的特殊能力,可以发出不同强度的闪光。小蓝共找到了N 枚宝石,第 i 枚宝石的 “闪亮度” 属性值为 Hi,小蓝将会从这 N 枚宝石中选出三枚进行组合,组合之后的精美程度 S 可以用以下公式来衡量:
其中 LCM 表示的是最小公倍数函数。小蓝想要使得三枚宝石组合后的精美程度 S 尽可能的高,请你帮他找出精美程度最高的方案。如果存在多个方案 S 值相同,优先选择按照 H 值升序排列后字典序最小的方案。
输入格式
第一行包含一个整数 N 表示宝石个数。第二行包含 N 个整数表示 N 个宝石的 “闪亮度”。
输出格式
输出一行包含三个整数表示满足条件的三枚宝石的 “闪亮度”。
样例输入
复制
5 1 2 3 4 9
样例输出
复制
1 2 3
提示
【评测用例规模与约定】
对于 30% 的评测用例:3 ≤ N ≤ 100,1 ≤ Hi ≤ 1000。
对于 60% 的评测用例:3 ≤ N ≤ 2000。
对于 100% 的评测用例:3 ≤ N ≤ 105,1 ≤ Hi ≤ 105。
最初33分的代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
int gcd3(int a, int b, int c)
{
return gcd(gcd(a, b), c);
}
int main()
{
ios::sync_with_stdio(false);
cout.tie(nullptr);
ll n;
cin >> n;
ll ar[100001],b[100001];
for(int i=0;i<n;i++){
cin>>ar[i];
}
sort(ar,ar+n);
ll ans = 0;
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
for (int k = j + 1; k < n; k++)
{
int s = gcd3(ar[i], ar[j], ar[k]);
if (s > ans)
{
ans = s;
b[0] = ar[i];
b[1] = ar[j];
b[2] = ar[k];
}
}
}
}
cout<<b[0]<<" "<<b[1]<<" "<<b[2];
return 0;
}
上面实际上是过不了1e5的,肯定会超时,用逆向做就可以了
#include <bits/stdc++.h>
using namespace std;
const int h = 1e5;
int main()
{
// m记录宝石个数
int n, m[h + 1] = {}, t, max = 0;
cin >> n;
for (int i = 0; i < n; i++)
{
// 亮度为t的宝石个数
cin >> t;
m[t]++;
// 精美程度一定小于等于最大的亮度
if (t > max)
max = t;
}
// 假设精美程度为i,从大到小遍历i的所有可能值
for (int i = max; i >= 1; i--)
{
int ans = 0, cnt = 0, num[3] = {};
for (int j = i; j <= max; j += i)
{
// 若m[j]有值,则找到m[j]个j的宝石
ans += m[j];
// 统计找到的宝石,直到三枚
for (int k = 0; k < m[j] && cnt < 3; k++)
num[cnt++] = j;
// 找到了三枚宝石,输出
if (ans >= 3)
{
cout << num[0] << " " << num[1] << " " << num[2];
return 0;
}
}
}
return 0;
}
四、数字接龙
题目描述
小蓝最近迷上了一款名为《数字接龙》的迷宫游戏,游戏在一个大小为N × N 的格子棋盘上展开,其中每一个格子处都有着一个 0 . . . K − 1 之间的整数。游戏规则如下:
1. 从左上角 (0, 0) 处出发,目标是到达右下角 (N − 1, N − 1) 处的格子,每一步可以选择沿着水平/垂直/对角线方向移动到下一个格子。
2. 对于路径经过的棋盘格子,按照经过的格子顺序,上面的数字组成的序列要满足:0, 1, 2, . . . , K − 1, 0, 1, 2, . . . , K − 1, 0, 1, 2 . . . 。
3. 途中需要对棋盘上的每个格子恰好都经过一次(仅一次)。
4. 路径中不可以出现交叉的线路。例如之前有从 (0, 0) 移动到 (1, 1),那么再从 (1, 0) 移动到 (0, 1) 线路就会交叉。
为了方便表示,我们对可以行进的所有八个方向进行了数字编号,如下图2 所示;因此行进路径可以用一个包含 0 . . . 7 之间的数字字符串表示,如下图 1是一个迷宫示例,它所对应的答案就是:41255214。
现在请你帮小蓝规划出一条行进路径并将其输出。如果有多条路径,输出字典序最小的那一个;如果不存在任何一条路径,则输出 −1。
输入格式
第一行包含两个整数 N、K。接下来输入 N 行,每行 N 个整数表示棋盘格子上的数字。
输出格式
输出一行表示答案。如果存在答案输出路径,否则输出 −1。
样例输入
复制
3 3 0 2 0 1 1 1 2 0 2
样例输出
复制
41255214
提示
【样例说明】行进路径如图 1 所示。
【评测用例规模与约定】对于 80% 的评测用例:1 ≤ N ≤ 5。对于 100% 的评测用例:1 ≤ N ≤ 10,1 ≤ K ≤ 10。
最终代码:
#include<bits/stdc++.h> // 引入整个标准库和C++ STL库
using namespace std; // 使用标准命名空间
int g[11][11]; // 棋盘,存储每个格子的数字
int d[11][11]; // 访问标记,表示当前格子是否已访问
int st[11][11]; // 状态数组,存储到达每个格子的方向
vector<int> path; // 存储最终的路径
// 移动方向的偏移量,dx 和 dy 分别表示 x 和 y 轴上的偏移
int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1};
int dy[] = {0, 1, 1, 1, 0, -1, -1, -1};
int n, k; // n 是棋盘的大小,k 是棋盘上数字的最大值
bool dfs(int x, int y, int cnt) { // 深度优先搜索函数
if (x == n - 1 && y == n - 1 && cnt == n * n) // 如果到达棋盘底部的最后一个格子,并且格子数量符合,返回 true
return true;
for (int i = 0; i < 8; i++) { // 遍历所有八个方向
int tx = x + dx[i]; // 计算目标x坐标
int ty = y + dy[i]; // 计算目标y坐标
// 检查目标位置是否在棋盘内,未被访问,并且满足数字序列条件
if (tx >= 0 && tx < n && ty >= 0 && ty < n && d[tx][ty] == 0 &&
((g[x][y] == k - 1 && g[tx][ty] == 0) || g[tx][ty] == g[x][y] + 1)) {
// 检查当前方向是否会导致路径交叉
if (i == 1 && (st[x - 1][y] == 3 || st[x][y + 1] == 7))
continue; // 从当前格子向右移动,检查是否与之前的路径交叉
if (i == 3 && (st[x + 1][y] == 1 || st[x][y + 1] == 5))
continue; // 从当前格子向下移动,检查是否与之前的路径交叉
if (i == 5 && (st[x][y - 1] == 3 || st[x + 1][y] == 7))
continue; // 从当前格子向左下移动,检查是否与之前的路径交叉
if (i == 7 && (st[x][y - 1] == 1 || st[x - 1][y] == 5))
continue; // 从当前格子向左上移动,检查是否与之前的路径交叉
st[x][y] = i; // 记录当前格子的方向
d[tx][ty] = 1; // 标记目标格子为已访问
path.push_back(i); // 将方向编号添加到路径中
if (dfs(tx, ty, cnt + 1)) // 递归搜索下一个位置
return true; // 如果找到路径,则返回 true
path.pop_back(); // 回溯,移除路径中的最后一个方向编号
d[tx][ty] = 0; // 回溯,重置目标格子的访问标记
st[x][y] = -1; // 回溯,重置当前格子的方向
}
}
return false; // 如果所有方向都不是解决方案,则返回 false
}
int main() {
cin >> n >> k; // 读取棋盘大小和数字的最大值
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> g[i][j]; // 填充棋盘
}
}
// 检查棋盘右下角的数字是否为 k-1,如果不是,则无法形成合法路径,输出-1
if (g[n - 1][n - 1] != k - 1) {
cout << -1;
return 0;
}
memset(st, -1, sizeof st); // 初始化状态数组,所有值设为 -1
d[0][0] = 1; // 标记起始格子为已访问
if (dfs(0, 0, 1)) { // 从(0, 0)开始深度优先搜索
for (auto i : path) // 输出找到的路径
cout << i;
} else {
cout << -1; // 如果没有找到路径,输出-1
}
return 0;
}
五、爬山
题目描述
小明这天在参加公司团建,团建项目是爬山。在 x 轴上从左到右一共有 n座山,第 i 座山的高度为 hi。他们需要从左到右依次爬过所有的山,需要花费的体力值为 S = Σni=1hi。
然而小明偷偷学了魔法,可以降低一些山的高度。他掌握两种魔法,第一种魔法可以将高度为 H 的山的高度变为 ⌊√H⌋,可以使用 P 次;第二种魔法可以将高度为 H 的山的高度变为 ⌊H/2⌋,可以使用 Q 次。并且对于每座山可以按任意顺序多次释放这两种魔法。
小明想合理规划在哪些山使用魔法,使得爬山花费的体力值最少。请问最优情况下需要花费的体力值是多少?
输入格式
输入共两行。
第一行为三个整数 n,P,Q。
第二行为 n 个整数 h1,h2,. . . ,hn。
输出格式
输出共一行,一个整数代表答案。
样例输入
复制
4 1 1 4 5 6 49
样例输出
复制
18
提示
【样例说明】将第四座山变为 ⌊√49⌋ = 7,然后再将第四座山变为 ⌊7/2⌋ = 3。体力值为 4 + 5 + 6 + 3 = 18。
【评测用例规模与约定】
对于 20% 的评测用例,保证 n ≤ 8,P = 0。
对于 100% 的评测用例,保证 n ≤ 100000,0 ≤ P ≤ n,0 ≤ Q ≤ n,0 ≤ hi ≤ 100000。
最终代码:
纯贪心,这样能拿92分,其实知道是哪种问题了导致过不了了,但是会超时
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, P, Q;
long long ans = 0;
priority_queue<int> h;
cin >> n >> P >> Q;
for (int i = 0; i < n; i++)
{
int hi;
cin >> hi;
h.push(hi);
}
while (P || Q)
{
//取出第一个数
int first = h.top();
h.pop();
//对最高的山进行两种操作,哪种更矮就用哪种
if (P && Q)
{
if (sqrt(first) <= first / 2)
{
h.push(sqrt(first));
P--;
}
else
{
h.push(first / 2);
Q--;
}
}
//如果只剩一种魔法了,就直接用
else if (P)
{
h.push(sqrt(first));
P--;
}
else if (Q)
{
h.push(first / 2);
Q--;
}
}
while (!h.empty())
{
ans += h.top();
h.pop();
}
cout << ans;
return 0;
}
六、拔河
题目描述
小明是学校里的一名老师,他带的班级共有 n 名同学,第 i 名同学力量值为 ai。在闲暇之余,小明决定在班级里组织一场拔河比赛。
为了保证比赛的双方实力尽可能相近,需要在这 n 名同学中挑选出两个队伍,队伍内的同学编号连续:{al1, al1+1, ..., ar1−1, ar1} 和 {al2, al2+1, ..., ar2−1, ar2},其中 l1 ≤ r1 < l2 ≤ r2。
两个队伍的人数不必相同,但是需要让队伍内的同学们的力量值之和尽可能相近。请计算出力量值之和差距最小的挑选队伍的方式。
输入格式
输入共两行。
第一行为一个正整数 n。
第二行为 n 个正整数 ai。
输出格式
输出共一行,一个非负整数,表示两个队伍力量值之和的最小差距。
样例输入
复制
5 10 9 8 12 14
样例输出
复制
1
提示
【样例说明】
其中一种最优选择方式:队伍 1:{a1, a2, a3},队伍 2:{a4, a5},力量值和分别为 10 + 9 + 8 = 27,12 + 14 = 26,差距为 |27 − 26| = 1。
【评测用例规模与约定】
对于 20% 的评测用例,保证 n ≤ 50。
对于 100% 的评测用例,保证 n ≤ 103,ai ≤ 109。
最终代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int n=1e6;
int a,b[n],c;
signed main()
{
cin>>a;
for(int i=1;i<=a;i++)
{
cin>>b[i];
}
set<int>t;
int an=1e18;
for(int i=a;i>=1;i--)
{
int v=0;
for(int j=i+1;j<=a;j++)
{
v+=b[j];
t.insert(v);
}
v=0;
for(int j=i;j>=1;j--)
{
v+=b[j];
if(t.size()==0)
{
continue;
}
if(v>*t.rbegin())
{
an=min(an,v-*t.rbegin());
}
else if(v<=*t.begin())
{
an=min(an,*t.begin()-v);
}
else
{
auto s=t.lower_bound(v);
an=min(an,*s-v);
s--;
an=min(an,v-*s);
}
}
}
cout<<an<<endl;
}