ブルーブリッジカップ省試合2020年第11回C/C++A組第2回プログラミング問題更新待ち


第六題:成績統計問題の説明
青さんは学生たちに試験を組織して、答案面の総得点は100点で、学生一人一人の得点は0から100の整数です.今度の試験の最高点、最低点、平均点を計算してください.【入力フォーマット】入力された最初の行には、試験人数を表す整数nが含まれる.次のn行は、各行に0〜100の整数を含み、1人の学生の得点を表す.
【出力形式】3行出力します.最初の行には、最高スコアを表す整数が含まれます.2行目には、最小スコアを表す整数が含まれます.3行目は実数を含み、四捨五入はちょうど2桁の小数を保持し、平均点を表す.
【サンプル入力】7 80 92 56 74 88,9910【サンプル出力】99,10171.29【評価例規模と約定】50%の評価例に対して、1≦n≦100.すべての評価例について、1≦n≦10000である.
#include 
#include 
#include 
#include 
using namespace std;


int main(){
     
	int n;
	cin >> n;
	int min=0x3f3f3f3f;
	int max=0;
	double sum =0;
	int temp;
	for(int i=0; i<n; i++){
     
		scanf("%d",&temp);
		if(temp<min) min = temp;
		if(temp>max) max = temp;
		sum += temp;
	}
	sum/=100.0;
	sum =  (long long)(sum*100 +0.5) * 1.0 /n;
	printf("%d
%d
%.2f
"
,max,min,sum); return 0; }

第七題:回文日付テーマ説明
2020年の春節期間中、2020年2月2日という特別な日が注目されました.この日付を「yyyyymmdd」の形式で8桁に書くと20200202となり、ちょうど1回の文数になるからです.私たちはこのような日付を返事の日付と呼んでいます.20200202は「千年に一度」という特別な日だという人もいる.これに対して明ちゃんはとても認めません.2年もしないうちに次の返事の日付です.20211202、2021年12月2日です.20200202は1つの返信日だけでなく、ABABBABA型の返信日でもあるという人もいます.これに対して明ちゃんも認めていません.約100年後に次のABABBABA型の返信日:21211212、2121年12月12日に出会うことができるからです.「千年に一度」ではなく、せいぜい「千年に二度」だ.8桁の日付を指定して、その日付の後に次の返信日と次のABABBABA型の返信日がそれぞれどの日なのか計算してください.
【入力形式】入力は、日付を表す8ビット整数Nを含む.
【出力形式】2行出力し、1行あたり8桁.1行目は次の返信日、2行目は次のABABBABA型の返信日を表します.
【サンプル入力】20200202【サンプル出力】20211202 21211212【評価用例規模と約定】すべての評価用例について、100000101≦N≦89991231、Nが合法的な日付の8桁表示であることを保証する
コード#コード#
#include 
#include 
#include 
#include 
#include 
using namespace std;
int months[]={
     0,31,28,31,30,31,30,31,31,30,31,30,31};
bool judge(int fi){
     
	int year = fi/10000;
	int month = fi/100%100;
	int day = fi%100;
	if(month<=0||month>12) return false;
	if(day==0 || ( month!=2&&day>months[month] ) ) return false;
	if(month == 2){
     
		int leap=0;
		if( (year%4==0 && year%100!=0) || year%400==0) leap=1;
		if(day > 28+leap) return false;
	}
	return true;
}

int main(){
     
	int  n,ans1=0,ans2=0;
	cin >> n;
	for(int i=n+1; i<=899912310; i++){
     
		if(!judge(i)) continue;
		int temp =i;
		int fi =0;//   
		while(temp){
     
			int t = temp % 10;
			fi = fi*10 + t;
			temp /= 10;
		}
		if(i==fi){
     	
			if(ans1==0) ans1 = i;
			if(i%10==i/100%10 && i/10%10==i/1000%10 && i%10!=i/10%10){
     
				ans2=i;
				break;
			}
		}
	}
	cout<<ans1<<endl<<ans2<<endl;
	return 0; 
} 

第八題子列分値題記述
1つの文字列Sについて、Sのスコアf(S)を、Sにおいてちょうど1回現れる文字数として定義する.例えば、f("aba")=1、f("abc")=3、f("aaa")=0である.文字列S[0...n-1](長さn)が与えられ、すべてのSに対する非空子列S[i...j](0≦i≦j【入力フォーマット】入力行には、小文字からなる文字列Sが含まれる.
【出力フォーマット】整数を出力して答えを表します.
【サンプル入力】ababc【サンプル出力】21【サンプル説明】サブ列f値:
a 1 ab 2 aba 1 aba 0 ababc 1 b 1 ba 2 bab 1 babc 2 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.
暴力コード
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 1e5+10;
int num[255];
int cal(string str){
     
	int len = str.length();
	int re=0;
	for(int i=0; i<len; i++){
     
		num[str[i]]++;
	}
	for(int i=0; i<len; i++){
     
		if(num[str[i]]==1) re++;
	}
	return re;
}
int main(){
     
	string str;
	cin >> str;
	int ans=0;
	int len = str.length();
	 for(int i=0; i<len; i++){
     
	 	for(int j=1; j<=len-i; j++){
     
	 		memset(num,0,sizeof(num));
	 		ans += cal(str.substr(i,j));
		 }
	 }
	 cout << ans << endl;
	return 0;
}

新しい考え方:各位置内のアルファベットの前回と次の位置を記録し、乗算することはその位置が全体に与える貢献値である.
#include
using namespace std;
const int N = 1e5+10;
typedef long long ll;
char str[N];
int pre[N]; // pre[i]                   
int nex[N]; // nex[i]   i              
int h[26]; //      a-z       (   1  ,       )
ll ans;
int main(){
     
    scanf("%s",str + 1); //     1       
    int len = strlen(str + 1);
    for(int i=1;i<=len;i++)
    {
     
        pre[i] = 1; // i - pre[i]                  + 1 == i - pre[i]
        nex[i] = len; //                     + 1 == nex[i] - 1,          
    }
    for(int i=1;i<=len;i++){
     
        int t = str[i] - 'a'; //         a-0 b-1 c-2 d-3 e-4.....
        pre[i] = h[t];  // z             t                   ,       h[t]     h[t]  pre[i]-----                   
        h[t] = i;
    }
    for(int i=0;i<26;i++) h[i] = len+1;
    for(int i=len;i>=1;i--){
     
        int t = str[i] - 'a';
        nex[i] = h[t]; //     ,          ,              ,      len+1
        h[t] = i;
    }
    for(int i=1;i<=len;i++)
    {
     
        ans+=(ll)(i-pre[i])*(nex[i]-i);
    }
    cout<<ans<<endl;
    return 0;
}