题意:给定字符串,判断是否能由aa,aaa,bb,bbb组成。
思路:其实我们可以发现,任何大于1的数都可以由2和3的组合组成。所以我们只需要判断是否存在单独的a或者单独的b就行了。说来惭愧,这题我刚开始考虑的太复杂了,导致Wrong了2发。呜呜呜,还是功力不太深厚啊。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
int t;
cin >> t;
for(int i = 0; i < t; i++) {
string s;
cin >> s;
char t = s[0], cnt = 0;
for(int j = 0; j < s.size(); j++) {
if(s[j] == t) cnt++;
else {
if(cnt < 2) {
break;
}
t = s[j];
cnt = 1;
}
}
if(cnt < 2) puts("NO");
else puts("YES");
}
return 0;
}
题意:给定n个数,每个数可以最多只进行一次操作(+1或者-1),判断能否通过这种操作,使得这个数组满足:
an−am==n−m(n>m)
也就是说元素之差等于距离之差。
思路:这样可以说是贪心吧?我的想法是: 对于一串连续的自然数,我们就把这一串数压缩,只用首尾两个数表示,最后将判断这些压缩的数对。但是有一点很重要:如果两个数相差大于3,那么就肯定是没救了。每个数对只能移动一次,我们用一个bool数组记录就好了。
代码:
using namespace std;
typedef pair<int,int>PII;
const int N = 2e5 + 10;
int q[N];
PII cnt[N];
bool st[N];
void solve() {
int n;
cin >> n;
for(int i = 0; i < n; i++) cin >> q[i];
int k = 0;
for(int i = 0; i < n; i++) {
int j;
for(j = i + 1; j < n; j++) {
if(q[i] + j - i != q[j]) break;
}
cnt[k].second = q[j-1];
cnt[k].first = q[i];
k++;
i = j-1;
}
for(int i = 0; i < k; i++) st[i] = false;
//for(int i = 0; i < k; i++) cout << cnt[i].first << ' ' << cnt[i].second << endl;
for(int i = 1; i < k; i++) {
if(cnt[i].first - cnt[i-1].second == 1) continue;
else if(cnt[i].first - cnt[i-1].second == 2) {
if(st[i-1]) {
cnt[i].second -= 1;
st[i] = true;
}else {
st[i] = true;
}
} else if(cnt[i].first - cnt[i-1].second == 3) {
if(st[i-1]) {
puts("NO");
return;
}
cnt[i].second -= 1;
st[i] = true;
} else if(cnt[i].first - cnt[i-1].second > 3) {
puts("NO");
return;
}
}
puts("YES");
}
signed main() {
int t;
cin >> t;
while(t--) {
solve();
}
return 0;
}
题意:给定一个序列a[n](表示n袋糖果的价格,每个糖果每天只能买一次)和一个金额k,每天a[n]的所有元素都会+1,问至多能买多少袋糖果(如果某一天k有剩余,那么第二天不会用到前一天剩余的钱)。
思路:先排序求前缀和,然后依次求出第i袋糖果最多可以买到的天数,最后相加就行了。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
#define int long long
#define pb push_back
void solve() {
int n, k;
cin >> n >> k;
vector<int>a;
for(int i = 0; i < n; i++) {
int x;
cin >> x;
a.pb(x);
}
sort(a.begin(), a.end());
int ans = 0, sum = 0;
for(int i = 0; i < a.size(); i++) {
sum += a[i];
if(sum <= k) {
ans += (k - sum) / (i + 1) + 1;
} else break;
}
cout << ans << endl;
}
signed main() {
int t;
cin >> t;
while(t--) {
solve();
}
return 0;
}
题意:给n个数,和一个数x,x表示有x个从1到x的自然数。将这x个自然数插入到这n个数中(可以是中间,可以是首尾)。求插入后的:|ai−ai+1|之和的最小值。
思路:分析,当要插入的值在a,b之间时,无论怎么插,结果都是b-a, 所以我们只需要判断这n个数的最大值mx和x的大小以及最小值mn和1的大小。当x大于mx的时候,我们可以把x插到头,此时增加的值为x - a[0], 插到尾时,增加的值为:x - a[n-1], 插到mx旁边时增加的值为:2 * (x - mx); 这里我推到一下为什么是2 * (x - mx)。 假设插到mx后面吧,并设mx后面跟着的数是ai。有:
... mx mx + 1 mx + 2... x ai, 此时增加的值为:x−mx+x−ai−(mx−ai)=2∗(x−mx)
求这三者最小值即可,mn和1也是相同的思考方式。
代码:
using namespace std;
const int N = 2e5 + 10;
int q[N];
//bool st[N];
//
void solve() {
int n, x;
cin >> n >> x;
int mx = 0, mn = N;
for(int i = 0; i < n; i++) {
cin >> q[i];
mx = max(mx, q[i]);
mn = min(mn, q[i]);
}
long long ans = 0;
for(int i = 0; i < n - 1; i++) ans += abs(q[i] - q[i+1]);
if(x > mx) ans += min(abs(q[0] - x), min(abs(q[n-1] - x), 2 * (x - mx)));
if(1 < mn) ans += min(abs(q[0] - 1), min(abs(q[n-1] - 1), 2 * (mn - 1)));
cout << ans << endl;
}
int main() {
int t;
cin >> t;
while(t--) {
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)