【青橋杯スプリント】青橋杯第11回地方大会 C++b組 実問 - プログラミング問題集

目次

質問 F: 成績統計

問題解決のアイデア:

コード:

質問 G: 回文日付

問題解決のアイデア:

コード:

質問 H: ストリング スコア

問題解決のアイデア:

コード:

 質問 I: 平面のセグメンテーション

問題解決のアイデア:

コード:

テスト問題 J: 文字列の並べ替え

問題解決のアイデア:

最後に書く:


質問 F: 成績統計

【問題解説】

Xiaolan は学生のために試験を組織し、論文の合計点は 100 点です。

各生徒のスコアは 0 から 100 までの整数です。

60点以上を合格と呼びます。

少なくとも 85 点が優れていると見なされます。

合格率と優良率は百分率で計算し、百分率記号の前の部分を四捨五入して整数にします。

【入力フォーマット】

入力の最初の行には、試験を受ける人数を示す整数 n が含まれます。

次の n 行。各行には、生徒の得点を表す 0 から 100 までの整数が含まれます。

【出力フォーマット】

それぞれ合格率と優良率を示すパーセンテージを含む 2 行を出力します。

パーセント記号の前の部分は整数に丸められます。

【入力例】

7
80
92
56
74
88
100
0

【出力例】

71%
43%

問題解決のアイデア:

これは簡単な模擬問題です。最初の質問は慎重に行う必要があります。問題はありません。

コード:

#include <iostream>
using namespace std;

int main() {
	int n;
	cin >> n;
	double a = 0, b = 0, score;
	for (int i = 0; i < n; i++) {
		cin >> score;
		if (score >= 60) a++;
		if (score >= 85) b++;
	}
    //%.0f能够自动四舍五入
	printf("%.0f%% %.0f%%", (a / n) * 100, (b / n) * 100);
	return 0;
}

質問 G: 回文日付

【問題解説】

2020 年の春節の期間中、2020 年 2 月 2 日という特別な日が注目を集めました。

この日付を「yyyymmdd」の形式で8桁の数字で書くと20200202なので、

まさに回文数。このような日付をパリンドローム日付と呼びます。

20200202年は「千年に一度」の特別な日だという人もいます。

Xiao Ming はこれに同意しません。次の回文の日付は 2 年以内です: 20211202、つまり 2021 年 12 月 2 日です。

20200202 は単なる回文日付ではなく、ABABBABA 型の回文日付でもあるという人もいます。

Xiao Ming もこれに反対します。

ABABBABA タイプの次の回文日付は約 100 年後に発生する可能性があるため、21211212 は 2121 年 12 月 12 日です。

「千年に一度」ではなく、せいぜい「千年に一度」です。

8 桁の日付を指定すると、

次の回文日付と、この日付以降の次の ABABBABA 型回文日付が何日であるかを計算してください。

【入力フォーマット】

入力には、日付を表す 8 桁の整数 N が含まれます。

【出力フォーマット】

それぞれ 1 オクテットの 2 行を出力します。

最初の行は、次の回文の日付を表します。

2 行目は、タイプ ABABBABA の次の回文日付を表します。

【入力例】

20200202

【出力例】

20211202
21211212

【評価ユースケースの規模と合意】

すべての評価ケースで、10000101 ≤ N ≤ 89991231 であり、N が有効な日付の 8 桁の表現であることを保証します。

問題解決のアイデア:

この質問の考え方は、その後の日付を列挙し、質問の要件を満たしているかどうかを判断することです。

データリターンによると、1000〜10000年を列挙する必要があります。

コード:

#include <iostream>
using namespace std;

int mon[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

//20211202
bool check1(int date) {
	int year = date / 10000;
	int month = date / 100 % 100;
	int day = date % 100;

	if (month > 12) return false;

	if (month == 2 
	&& ((year % 4 == 0 && year % 100) || year % 400 == 0) 
	&& day > mon[month] + 1) return false;

	if (month != 2 && day > mon[month]) return false;

	return true;
}

//21211212
bool check2(int date) {
	int year = date / 10000;
	int month = date / 100 % 100;
	int day = date % 100;

	if (month > 12) return false;

	if (month == 2 
	&& ((year % 4 == 0 && year % 100) || year % 400 == 0) 
	&& day > mon[month] + 1) return false;

	if (month != 2 && day > mon[month]) return false;

	if (day != month) return false;

	return true;
}

int main() {
	int date1;
	cin >> date1;
	bool flag1 = false, flag2 = false;
	for (int i = 1000; i < 10000; i++) {
		int date = i, x = i;
		//将date翻转接上原来的date,就能让该日期变成一个回文串
		for (int i = 0; i < 4; i++) {
			date = date * 10 + x % 10;
			x /= 10;
		}
		//判断翻转之后该日期是否合法(题目第一个要求)
		if (!flag1 && date > date1 && check1(date)) {
			flag1 = true;
			cout << date << endl;
		}
		//判断翻转之后该日期是否合法以及是否是 ABABBABA 型
		if (!flag2 && date > date1 && check2(date)) {
			flag2 = true;
			cout << date << endl;
		}

		if (flag1 && flag2) break;
	}
	return 0;
}

質問 H: ストリング スコア

【問題解説】

文字列 S について、S のスコア f (S) を、S に現れる個別の文字の数として定義します。

たとえば、f("aba") = 2、f("abc") = 3、f("aaa") = 1 です。

ここで、文字列 S[0..n − 1] (長さ n) が与えられると、

S のすべての空でない部分文字列 S [ i..j ] (0 ≤ i ≤ j < n) の f (S [ i..j ]) の合計を計算してください

【入力フォーマット】

小文字で構成される文字列 S を含む行を入力します。

【出力フォーマット】

答えを表す整数を出力します。

【入力例】

ababc

【出力例】

28

【記載例】

子串    f值
a        1
ab       2
aba      2
abab     2
ababc    3
 b       1
 ba		 2
 bab	 2
 babc 	 3
   a	 1
   ab	 2
   abc	 3
    b	 1
    bc	 2
     c	 1

【評価ユースケースの規模と合意】

評価ケースの 20% で 1 ≤ n ≤ 10。

評価ケースの 40% で 1 ≤ n ≤ 100。

評価ケースの 50% で 1 ≤ n ≤ 1000。

評価ケースの 60% では、1 ≤ n ≤ 10000 です。

すべての評価ケースで 1 ≤ n ≤ 100000。

問題解決のアイデア:

ここで使用するアイデアは、STL を使用することです。

set, set の特性は、自動的に重複排除に役立ちます。

次に、文字列を列挙してカウントするだけです。

コード:

#include <iostream>
#include <string>
#include <set>;
using namespace std;

int main() {
	string s;
	cin >> s;
	int sum = 0;
	for (int i = 0; i < s.size(); i++) {
		set<char> p;
		for (int j = i; j < s.size(); j++) {
			p.insert(s[j]);
			sum += p.size();//去重之后的size就是字母的种类
		}
	}
	cout << sum << endl;
	return 0;
}

 質問 I: 平面のセグメンテーション

【問題解説】

平面上には N 本の直線があり、i 番目の直線は y = Ai · x + Bi です。

これらの線が平面をいくつかの部分に分割する方法を計算します。

【入力フォーマット】

最初の行には整数 N が含まれています。

次の N 行には、それぞれ 2 つの整数 Ai; Bi が含まれています。

【出力フォーマット】

答えを表す整数。

【入力例】

3
1 1
2 2
3 3

【出力例】

6

【評価ユースケースの規模と合意】

評価ケースの 50% では、1 ≤ N ≤ 4、−10 ≤ Ai、Bi ≤ 10 です。

すべての評価ケースで、1 ≤ N ≤ 1000、-100000 ≤ Ai; Bi ≤ 100000。

問題解決のアイデア:

数学のクズは、それは本当にできないと言いました。. . ウーウーウー。. .

コード:

コード参照:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;

using namespace std;
const int N = 100010;
string s;
int pre[N],ne[N];
int a[27];

int main()
{
	cin >>s;
	s = "0" + s;
	
	//获取字符串长度
	int len = s.length();
	
	//有步初始化,我直接声明的全局变量,是可以不用的,为了和后面操作想呼应,就写完整吧
	for(int i = 0; i < 27;i++) a[i] = 0;
	
	//找前一个相同字符的下标
	for(int i = 1; i < len;i++)
	{
		//将'a'变成偏移量,获得
		int index = s[i] - 'a';
		pre[i] = a[index];
		a[index] = i;
	}
	
	
	for(int i = 0; i < 27;i++) a[i] = len;
	
	//找下一个相同字符的下标
	for(int i = len - 1; i >= 1;i--)
	{
		int index = s[i] - 'a';
		ne[i] = a[index];
		a[index] = i;
	}
	
	LL ans = 0;
	
	for(int i = 1; i <len;i++)
		ans += (LL)(i - pre[i]) * (ne[i] - i);
		
	cout << ans << endl;
	
	return 0;
}

テスト問題 J: 文字列の並べ替え

問題解決のアイデア:

見ないで、最後の質問すらできない

もちろん、この質問はできません。. .

最後に書く:

以上がこの記事の内容です、お読みいただきありがとうございます。

この記事が気に入ったら、いいねとコメントをお願いします。また、ご意見をお書きください。

私と一緒にプログラミングを学びたい場合は、私に従ってください。私たちは一緒に学び、成長します。

今後もより質の高いコンテンツを出力していきますので、よろしくお願いします。 

おすすめ

転載: blog.csdn.net/Locky136/article/details/129874506