赞
踩
目录

【试题解析】
枚举1-n,取出中满足题意的数累加即可。
- #include <iostream>
-
- using namespace std;
-
- const int N = 10010;
-
- int main()
- {
- int n;
- cin >> n;
- int res = 0;
- for(int i = 1; i <= n; i ++) //枚举1-n的所有数
- {
- int x = i;
- while(x)
- {
- int t = x % 10; //每次取出末位的数
- if(t == 0 || t == 1 || t == 2 || t == 9)
- {
- res += i;
- break;
- }
- x /= 10; //将末位的数移去
- }
- }
- cout << res;
- return 0;
- }



【试题解析】
找规律+双指针,双指针i, j依次枚举每层深度的起点和终点,依次记录每层的权值,输出最大权值对应的层数即可。
-
- #include <iostream>
- #include <cstring>
- #include <climits>
-
- using namespace std;
-
- const int N = 100010;
-
- typedef long long LL;
-
- int q[N];
- int n;
-
- int main()
- {
- cin >> n;
- for(int i = 1; i <= n; i ++)
- scanf("%d", &q[i]);
-
- LL maxv = INT_MIN, res = 0;
- int depth = 1;
- for(int i = 1; i <= n; i *= 2) //枚举每一层的起点
- {
- LL s = 0;
- for(int j = i; j <= i * 2 - 1 && j <= n; j ++) //对于每一层的起点i,分析可知终点为i * 2 - 1
- {
- s += q[j];
- }
- if(s > maxv)
- {
- maxv = s, res = depth; //记录最大值及对应的层数
- }
- depth ++;
- }
- cout << res;
- return 0;
- }
-
-



【题目解析】
两种做法:1.暴力枚举每一个公差d,找到满足题意的最大公差, 根据 (a[n - 1] - a[0]) / d,
a[n - 1]和a[0]已定,取d最大,即可保证项数最小。
2.枚举任意两个数的差,为kd(k为整数),求出所有kd的最大公约数,即为最大公差。
两种方法在蓝桥杯官网都能AC,但理论上来说第一种暴力的方法时间复杂度为O()会存在被卡数据的情况。
- //暴力做法
- #include <iostream>
- #include <algorithm>
-
- using namespace std;
-
- const int N = 100010;
-
- int a[N];
-
- int n;
-
- int main()
- {
- cin >> n;
- for(int i = 0; i < n; i ++) scanf("%d", &a[i]);
-
- sort(a, a + n);
-
- int d = a[1] - a[0];
-
- if(a[n - 1] == a[0]) cout << n; //特判公差为0的情况,此时项数最少即为n
- for(int j = d; j >= 1; j --)
- {
- bool falg = true;
- for(int i = 1; i < n; i ++)
- {
- if((a[i] - a[i - 1]) % j)
- {
- falg = false;
- break;
- }
- }
- if(falg == true)
- {
- cout << (a[n - 1] - a[0]) / j + 1;
- break;
- }
- }
- return 0;
- }

- //求kd最大公约数的方法
- #include <iostream>
- #include <algorithm>
- #include <cstring>
-
- using namespace std;
-
- const int N = 1e5 + 10;
-
- int gcd(int a, int b)
- {
- return b? gcd(b, a % b) : a;
- }
-
- int a[N];
-
- int n;
-
- int main()
- {
- cin >> n;
- for(int i = 0; i < n; i ++) scanf("%d", &a[i]);
- sort(a, a + n);
- int d = a[1] - a[0];
- if(d == 0)
- cout << n;
- else
- {
- for(int i = 1; i < n; i ++)
- {
- d = gcd(d, a[i] - a[0]);
- }
- cout << (a[n - 1] - a[0]) / d + 1;
- }
- return 0;
- }


【试题解析】

贪心,摘自AcWing 1247. 后缀表达式+思维图解 - AcWing 的图解,分析可知当M > 0时,我们总可以将M个‘ - ’号化为一个,此时我们只需减去A中的最小值,再加上A中最大值,剩余的数如果大于0我们就加上,小于0就减去。(代码很简单,难在理解如何将M个' - '化为一个' - ')
- #include <iostream>
- #include <cstring>
- #include <algorithm>
- #include <cmath>
-
- using namespace std;
-
- typedef long long LL;
-
- int n, m, k;
-
- const int N = 2e5 + 10;
-
- int a[N];
-
- int main()
- {
- cin >> n >> m;
- k = n + m + 1;
- for(int i = 0; i < k; i ++) scanf("%d", &a[i]);
-
- sort(a, a + k);
- LL res = 0;
-
- if(!m)
- for(int i = 0; i < k; i ++ ) res += a[i];
- else
- {
- res = res + a[k - 1] - a[0];
- for(int i = 1; i < k - 1; i ++)
- res += abs(a[i]); //加上大于0的数和减去小于0的数都可以记为加上该数的绝对值
- }
- cout << res;
- return 0;
- }




【试题解析】
又是一道贪心题,这题没写,转发AcWing 1248. 灵能传输--详细说一些细节 - AcWing大佬的题解
- #include "bits/stdc++.h"
-
- using namespace std;
-
- typedef long long LL;
-
- const int N = 3e5 + 10;
-
- int t, n;
- LL s[N], a[N]; // s为前缀和数组 a为存放前缀和顺序的数组
- bool st[N];
-
- int main()
- {
- cin >> t;
- while (t--)
- {
- cin >> n;
- memset(st, 0, sizeof st);
- for (int i = 1; i <= n; i++)
- cin >> s[i], s[i] += s[i - 1];
- LL s0 = s[0], sn = s[n];
- if (s0 > sn)
- swap(s0, sn);
- sort(s, s + n + 1);
- // 寻找排完序后s0和sn的位置
- // 如果s0和sn相同的话则前面的为s0 后面的为sn
- for (int i = 0; i <= n; i++)
- if (s[i] == s0)
- {
- s0 = i;
- break;
- }
- for (int i = n; i >= 0; i--)
- if (s[i] == sn)
- {
- sn = i;
- break;
- }
- int l = 0, r = n;
- for (int i = s0; i >= 0; i -= 2)
- {
- a[l++] = s[i];
- st[i] = 1;
- }
- for (int i = sn; i <= n; i += 2)
- {
- a[r--] = s[i];
- st[i] = 1;
- }
- for (int i = 0; i <= n; i++)
- if (!st[i])
- a[l++] = s[i];
- LL res = 0;
- for (int i = 1; i <= n; i++)
- res = max(res, abs(a[i] - a[i - 1]));
- cout << res << endl;
- }
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。