赞
踩
给一个数列,每次操作可以把前一部分每个数加1,后一部分每个数减1,问至少操作多少次可以让数列非递增
先遍历每一个数,如果有逆序的直接输出0
否则找到相邻元素最小的差值,最少的操作次数就是让这个最小的差值的两个元素变成逆序,除以2加1即可
#include <bits/stdc++.h> using namespace std; int main() { int t; cin >> t; while (t -- ) { int n; cin >> n; vector<int> a(n); for (int i = 0; i < n; i ++ ) cin >> a[i]; int l, r, minn = 0x3f3f3f3f; bool flag = true; for (int i = 1; i < n; i ++ ) { if (a[i] < a[i - 1]) { cout << 0 << endl; flag = false; break; } if (a[i] - a[i - 1] < minn) { minn = a[i] - a[i - 1]; l = i - 1, r = i; } } int ans = minn / 2 + 1; if (flag) cout << ans << endl; } }
给定斐波那契数列的第 k 项是 n,问存在多少这样的数列
设第一个数是 x,第二个数是 y
那么第三个数 x + y
,第四个数x + 2 * y
,第五个数2 * x + 3 * y
…
可以推出,x 的系数是 0 1 1 2 3 5 …,y 的系数是 1 1 2 3 5 8…
现有斐波那契数列(下标从1开始) 0 1 1 2 3 5 8…
那么 x 的系数 a 就是 fib[i - 1]
y 的系数 b 就是fib[i]
于是问题转换成了a * x + b * y = n
,求xy有多少种取值情况,要求xy均为整数且 x <= y
,对 x 逐项枚举即可
#include <bits/stdc++.h> using namespace std; int main() { int t; cin >> t; vector<int> fib(31); function<void(void)> init = [&](void) { fib[1] = 0, fib[2] = 1; for (int i = 3; i <= 30; i ++ ) fib[i] = fib[i - 1] + fib[i - 2]; }; init(); while (t -- ) { int n, k; cin >> n >> k; if (k > 30) { cout << "0\n"; continue; } int x, y; int a, b; int ans = 0; a = fib[k - 1], b = fib[k]; for (x = 0; x <= n / 2; x ++ ) if ((n - (a * x)) % b == 0 && (n - (a * x)) / b >= x) ans ++ ; cout << ans << '\n'; } }
有个从1开始逐渐递增的集合,每次操作给出任意个位数,删去给出位数上的数字,得到新数列,现给出操作次数和每次操作删去的位数,求操作完后的第一位是几
从每一轮当前的第一位数字开始遍历,如果当前遍历到的这位数字位于a[i]
和a[i - 1]
之间,那么它的前 i 个位置都会被删去
#include<bits/stdc++.h> using namespace std; using LL = long long; const int N = 2e5 + 5; LL a[N]; inline void solve() { LL n, k; cin >> n >> k; for (int i = 0; i < n; i++) cin >> a[i]; LL j = 0, ans = 1; // ans表示目前的第一位 j表示截至目前已经处理过的位数 while (k--) { while (j < n && a[j] <= ans + j) j++; ans += j; // 更新该轮结束后的第一位,也就是该轮刚开始时的第一位加上该轮已处理过的位数 } cout << ans << endl; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int T; cin >> T; while (T--) solve(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。