2023 河南ccpc
目录
A(签到题)
H(贪心)
F(单调队列模拟滑动窗口)
C(贪心)
G(模拟)
题目链接:
https://codeforces.com/gym/104354/attachments/download/20061/statements_2.pdf
vp赛时做出来了:ACFH,难度排序(简单到难):AHFC
赛后G
题解顺序按难度顺序来
A(签到题)
按题目要求先枚举a的所有可能情况,在挨个验证b是否符合如果符合就直接输出HE接着return,否则循环结束输出NaN,注意需要特判字符串长度为1的情况,因为题目要求ab都是非空字符串
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define PII pair<int,int>
//#define x first
//#define y second
//priority_queue<int, vector<int>, greater<int>> pq;//小根堆
const int N=2e5+10;
void solve()
{map<char,int>m;string s;cin >> s;if(s.size()==1){cout << "NaN" << endl;return ; }for(int i=0;i<s.size();i++){m[s[i]]++;if(m[s[i]]>1){cout << "NaN" << endl;return ;}string s1(s,i+1,s.size()-1-i);//截出字符串bstring s2(s,i+1,s.size()-1-i);reverse(s1.begin(),s1.end());if(s1==s2){cout << "HE" << endl;return ; }}cout << "NaN" << endl;
}
signed main(){ios::sync_with_stdio(false);cin.tie(nullptr);int q;cin >> q;while(q--)solve();
}
H(贪心)
题目简述:给定两个正整数n,k,要求构造一个长度为k的数组a[N],使得数组和为n,并且0<=a[i]<=n;让你求出对a数组中每个值进行四舍五入后再求和的最大值和最小值,并输出。
思路:贪心的想,要想使得最后的和尽可能大,则要使得数组中每一个数尽可能为0.5,因为0.5是四舍五入的最优策略
同样如果要想是=使得最后的和尽可能小,则要使得数组中每一个数尽可能为0.499999999,这里我们运用极限的思想,也看做0.5(无限趋近于0.5,但不会等于0.5),k-1个数设置为0.5(趋近于),所以这k-1个数求和为0,最后一个数是n-(k-1)*0.5,和为round(n-(k-1)*0.5)
我们实际减的并不是0.5而是不断趋近于0.5的数,但是这并不影响结果,我们可以举例来验证一下,减完之后的小数部分是只有两种情况1是为整数,2是为0.5,当为整数时就算加上多减的那一点点也不会五入,当为0.5时就算不加也依旧五入~
注意:
四舍五入:round()函数
向上取整:ceil()函数
向下取整:floor()函数
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define PII pair<int,int>
//#define x first
//#define y second
//priority_queue<int, vector<int>, greater<int>> pq;//小根堆
const int N = 5e5 + 10;
void solve()
{int n,k;cin >> n >>k;int m=n*2;//看n能分成几个0.5if(m<k)//如果<k,那么max:数组m个数设置成0.5,k-m设置成0;min:数组每个数都可以设置成>0&&<0.5的值{cout << 0 << ' ' << m<<endl;}else {cout <<(int)round((n-(k-1)*0.5)) << ' ' << (int)round((n-(k-1)*0.5))+k-1<<endl;}
}
signed main() {ios::sync_with_stdio(0);cin.tie(0);int q;cin >> q;while(q--){solve();}
}
F(单调队列模拟滑动窗口)
题目简述:给定两个整数n,k,和一个长度为n的一个数组,要求从数组中选出k个数,找这两个数乘积的最小值
思路:先排序,这样最小化两个数之间的距离,然后求差分数组,对差分数组进行滑动窗口,使用双端队列维护单调队列实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define PII pair<int,int>
const int N=5e5+10;
int a[N],d[N];
signed main(){ios::sync_with_stdio(false);cin.tie(nullptr);int n,k;cin >> n >> k;for(int i=0;i<n;i++){cin >>a[i];}sort(a,a+n);for(int i=1;i<n;i++){d[i]=a[i]-a[i-1];}deque<int>q;int ans=1e18;for(int i=1;i<n;i++){while(!q.empty()&&d[i]<d[q.back()]){q.pop_back();}
//保证队头是最小值,如果当前枚举值比队尾小那么就弹出队尾q.push_back(i);if(i>=k-1){
//找到了k个元素 while(q.front()<=i-k+1){q.pop_front();}
//看左边是否超出窗口,对超出窗口的弹出 ans=min(ans,(a[i]-a[i-k+1])*d[q[0]]);
//不断更新ans }}cout << ans << endl;
}
C(贪心)
根据这个数据范围,很容易想出,不论length为几,只要重复,那么前1000个在后续当中一定会出现;
#include <bits/stdc++.h>
#define int long long
using namespace std;
string s1;void solve(){cin>>s1;string s2=s1.substr(0,1000);s1.erase(0,1000);if(s1.find(s2)!=-1) cout<<"No"<<'\n';else cout<<"Yes"<<'\n';
}
signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int p=1;while(p--)solve();return 0;
}
G(模拟)
思路:扣数字,扣字符串,注意判断是否溢出
#include <iostream>
#include <string>
#include <vector>
using namespace std;// 数字0-9的大字体显示定义
const vector<string> anum = {".................................................................................",".................................................................................",".0000000.......1.2222222.3333333.4.....4.5555555.6666666.7777777.8888888.9999999.",".0.....0.......1.......2.......3.4.....4.5.......6.............7.8.....8.9.....9.",".0.....0.......1.......2.......3.4.....4.5.......6.............7.8.....8.9.....9.",".0.....0.......1.2222222.3333333.4444444.5555555.6666666.......7.8888888.9999999.",".0.....0.......1.2.............3.......4.......5.6.....6.......7.8.....8.......9.",".0.....0.......1.2.............3.......4.......5.6.....6.......7.8.....8.......9.",".0000000.......1.2222222.3333333.......4.5555555.6666666.......7.8888888.9999999.","................................................................................."
};// 上标数字0-9的大字体显示定义
const vector<string> bnum = {".............................................................",".00000.....1.22222.33333.4...4.55555.66666.77777.88888.99999.",".0...0.....1.....2.....3.4...4.5.....6.........7.8...8.9...9.",".0...0.....1.22222.33333.44444.55555.66666.....7.88888.99999.",".0...0.....1.2.........3.....4.....5.6...6.....7.8...8.....9.",".00000.....1.22222.33333.....4.55555.66666.....7.88888.99999.",".............................................................",".............................................................",".............................................................","............................................................."
};// 符号的大字体显示定义
const vector<string> cnum = {".................................",".................................",".........IIIIIII.N.....N.FFFFFFF.","............I....NN....N.F.......",".=======....I....N.N...N.F.......","............I....N..N..N.FFFFFFF.",".=======....I....N...N.N.F.......","............I....N....NN.F.......",".........IIIIIII.N.....N.F.......","................................."
};// 安全的幂运算,检测溢出
long long safe_pow(long long a, long long b) {if (a == 0) return 0;if (a == 1) return 1;long long result = 1;for (long long i = 0; i < b; i++) {result *= a;if (result <a||result>1e18) {return -1; // 溢出}}return result;
}int main() {int t;cin >> t;while (t--) {string input;cin >> input;// 解析输入中的底数和指数long long base = 0, exponent = 0;bool in_exponent = false;for (char c : input) {if (c == '{' || c == '^') {in_exponent = true;continue;}if (c == '}') {in_exponent = false;continue;}if (isdigit(c)) {if (in_exponent) {exponent = exponent * 10 + (c - '0');} else {base = base * 10 + (c - '0');}}}// 计算结果string result_str;long long result = safe_pow(base, exponent);if (result == -1) {result_str = "INF";} else {result_str = to_string(result);}// 构建最终显示字符串string display_str = input + "=" + result_str;// 显示结果for (int i = 0; i < 10; i++) {bool in_superscript = false;for (char c : display_str) {if (c == '{' || c == '^') {in_superscript = true;continue;}if (c == '}') {in_superscript = false;continue;}// 处理等号和INF字符if (c == '=') {cout << cnum[i].substr(0, 8);} else if (c == 'I') {cout << cnum[i].substr(8, 8);} else if (c == 'N') {cout << cnum[i].substr(16, 8);} else if (c == 'F') {cout << cnum[i].substr(24, 8);} else if (isdigit(c)) {// 显示数字int digit = c - '0';if (in_superscript) {cout << bnum[i].substr(digit * 6, 6);} else {cout << anum[i].substr(digit * 8, 8);}}}cout << "." << endl;}cout << endl;}return 0;
}