A题:
定义一个空数组a[]表示每个数出现过几次
每输入一个数据k,就让a[k] ++,表示k在场中已经出现了至少一次
如果a[k]==1说明 k 在场出现了第一次,这时直接输出即可,反之不输出
ac代码:
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int n;
int a[N];
int main()
{
cin >> n;
while(n --)
{
int x;
cin >> x;
a[x] ++;
if(a[x] == 1) cout << x << " ";
}
return 0;
}
B题:
ac代码:
#include <iostream>
using namespace std;
int main(){
double a;
cin >> a ;
cout << (int)(a * 100) << '%' ;
}
C题:
打表题,其中一个公式是把 1 到 n*n 的数累加起来 sum ,幻和 sum/边 ,中间数 sum/n/n 记得开 long long
ac代码:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
long long n ;cin >> n;
long long a = ceil(n * n / 2.0);
cout << a * n << ' ' << a << endl;
}
D题:
i:行, j:列
按列排序,与行无关,说明在排完 j 这一列之前 j 不会改变,那么列循环就应该在最外侧,
然后按照冒泡(sort)排序排就行
ac代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int p[N][N];
int main (){
int n ; cin >> n ;
for(int i = 0 ; i < n ; i ++ ){
for(int j = 0 ; j < n ; j ++ ){
cin >> p[j][i];
}
}
for(int i = 0 ; i < n ; i ++ ){
sort(p[i], p[i] + n);
}
for(int i = 0 ; i < n ; i ++ ){
for(int j = 0 ; j < n ; j ++ ){
cout << p[j][i] << ' ' ;
}
cout << endl;
}
}
E题:
创建两个数组分别将数值输入,根据公式分别求出分子和分母,数值可能过大,需要开 long long ,分母可以利用pow()函数,根据求最大公约数进行约分,可以利用gcd()函数求出最大公约数,分子和分母同时除以最大公约数并按格式输出(分子/分母),分子分母可能相等,结果为1,需要进行特殊判断。
ac代码:
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
long long d[1000], p[1000];
long long gcd(long long a,long long b) {
return b > 0 ? gcd(b, a % b) : a ;
}
int main() {
long long n , a ,b;cin >> n >> a >> b;
for(int i = 0 ; i < n ; i ++ ) cin >> d[i];
for(int i = 0 ; i < n ; i ++ ) cin >> p[i];
long long w = 0 ,s = 0 , sum1= 0 ,sum2 = 0;
for(int i = 0 ;i < n ; i ++) w += d[i] * p[i];
for(int i = 0 ;i < n ; i ++) {
sum1 += d[i];
sum2 += p[i];
}
s += pow(sum1, a) + pow(sum2, b);
long long t = __gcd(w, s);
if(w == s) {
cout << 1 << endl;
return 0;
}
cout << w / t << '/' << s / t << endl;
}
F题:
找连续字符串"Huade",并在该字符串后面加上"yyds",可以利用string的find查找函数与insert插入函数直接进行操作,也可以暴力操作,最后特判 0 即可。
ac代码:
#include <iostream>
using namespace std;
int main(){
string s;
cin >> s ;
string H = "Huade";
int t = 0;
int cnt = 0 ;
while(true){
t = s.find(H, t);
if(t == -1){
break;
}
cnt ++ ;
s.insert(t + H.size(), "yyds");
t++;
}
if(cnt == 0){
cout << 0 ;
return 0;
}
cout << cnt << endl << s << endl;
}
G题:
出现了排版错误,正确题目链接:https://ac.nowcoder.com/acm/contest/71505/G
密码:hdacm2023
(我就说我怎么检查了5遍测试点都没有问题。。。)
思路:
线性 dp ,状态表示为 f (i , j) ,i 表示当前原始字符串位置(可以压缩掉),j 表示当前目标字符串的下标。
f (i , j) 的值表示为在原始字符串下标 0 ~ i 的字符串中,有目标字符串下标 0 ~ j 的字符串 的子序列个数。
ac代码:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 10010 , mod = 1000000007;
typedef long long LL;
LL dp[N][30];
string str , go;
int n , m;
int main()
{
cin >> n >> m;
cin >> str >> go;
for(int i = 0 ; i <= n ; i ++)
dp[i][0] = 1;
for(int i = 1 ; i <= n ; i ++)
{
for(int j = 1 ; j <= m ; j ++)
dp[i][j] = dp[i - 1][j];
int idx = go.find(str[i - 1]) + 1;
if(idx > 0){
dp[i][idx] += dp[i - 1][idx - 1] %= mod;
}
}
cout << dp[n][m] % mod;
}
H题:
循环匹配字符串,遇到?默认为满足。
ac代码:
#include <iostream>
using namespace std;
int main(){
string a , b ; cin >> a >> b;
int cnt = 0;
for(int i = 0 ; i < a.size() ; i ++ ){
int j = i;
int t = 0;
while(j < a.size()){
if(a[j] == b[t] || a[j] == '?'){
j ++ ;
t ++ ;
}else {
break;
}
if(t == b.size()) {
cnt ++ ;
break;
}
}
}
cout << cnt << endl;
}
I题:
标准BFS,每一步的步长改为 2 就行,注意边界问题。
ac代码:
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1000;
int p[N][N];
int dx[]= {2,2,-2,-2}, dy[] = {2,-2,-2,2};
int n , m;
void dfs(int x , int y){
p[x][y] = 0;
queue<pair<int,int>> q;
q.push({x, y});
while(!q.empty()){
auto t = q.front();
q.pop();
for(int i = 0 ; i < 4 ; i ++ ){
int xi = t.first + dx[i] , yj = t.second + dy[i];
if(xi >= 0 && xi < n && yj >= 0 && yj < m && p[xi][yj] == -1){
q.push({xi, yj});
p[xi][yj] = p[t.first][t.second] + 1;
}
}
}
}
int main() {
int x, y;
cin >> n >> m >> x >> y;
x--;
y--;
memset(p, -1, sizeof(p));
dfs(x, y);
for(int i = 0 ; i < n ; i ++ ){
for(int j = 0 ; j < m ; j ++ ){
cout << p[i][j] << ' ' ;
}
cout << endl;
}
}
J题:
约瑟夫环,创建一个链表,让这个链表的尾部指向头部,打印出每次删掉的元素,循环直到链表中只剩一个元素为止。
注意开始编号与轮数的定义。
ac代码:
#include <iostream>
#include <vector>
using namespace std;
vector<int> V;
int main() {
int n , k;cin >> n >> k;
for(int i = 0 ; i < n ; i ++ ){
int a; cin >> a ;
V.push_back(a);
}
int t = 0 ;
while(V.size() > 1){
vector<int>::iterator it = V.begin();
t = (t + k + 1)% V.size();
cout << V[t] << ' ' ;
V.erase(it + t);
t -- ;
}
}
K题:
签到题,先输入大圆的半径为R,小圆的半径为r,被切前圆锥的高为H,切去的圆锥高度为h,利用题目公式分别求出半球和圆台的体积相加,利用printf的小数输出格式进行输出,保留两位小数。
注意精度问题。
ac代码:
#include <iostream>
using namespace std;
const double PI = 3.14;
int main() {
double R , r , H ,h;
cin >> R >> r >> H >> h ;
double s = 4.0 / 3.0 * PI * R * R * R / 2;
double f = (1.0 / 3.0 * PI * R * R * H) - (1.0 / 3.0 * PI * r * r * h);
double res = s + f;
printf("%.2f", res);
}
L题:
线段树,先创建一个足够大的线段树,维护该线段树,初始给出的单词视为加入元素,后续每次查询按照模板编写,每个线段中所推算的值为字典序最大的字符串,直接用max函数比较即可。
ac代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 100010;
int n , q;
struct tree{
int l , r;
string v;
}tr[4 * N];
void pushup(int u)
{
tr[u].v = max(tr[2 * u].v , tr[2 * u + 1].v);
}
void build(int u , int l , int r)
{
tr[u].l = l , tr[u].r = r;
if(l == r) return;
int mid = (l + r) >> 1;
build(2 * u , l , mid);
build(2 * u + 1 , mid + 1 , r);
}
void re(int u , int old , string neu)
{
if(tr[u].l == old && tr[u].r == old) tr[u].v = neu;
else{
int mid = (tr[u].l + tr[u].r) >> 1;
if(old <= mid) re(u * 2 , old , neu);
else re(u * 2 + 1 , old , neu);
pushup(u);
}
}
string query(int u , int l , int r)
{
if (tr[u].l >= l && tr[u].r <= r) return tr[u].v; // 树中节点,已经被完全包含在[l, r]中了
int mid = (tr[u].l + tr[u].r) >> 1;
string v = "";
if (l <= mid) v = query(u << 1, l, r);
if (r > mid) v = max(v, query(u << 1 | 1, l, r));
return v;
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> q;
build(1 , 1 , N);
for(int i = 1 ; i <= n ; i ++){
string str;
cin >> str;
re(1 , i , str);
}
//U:更改 Q:查询
while(q --)
{
char ch; cin >> ch;
if(ch == 'U'){
int idx; string x;
cin >> idx >> x;
re(1 , idx , x);
}
else{
int l , r;
cin >> l >> r;
string t = query(1 , l , r);
if(t.size() <= 0)
t += "null";
cout << t << endl;
}
}
}