1. 程式人生 > >第七屆藍橋杯C/C++ A組省賽題解

第七屆藍橋杯C/C++ A組省賽題解

1.網友年齡

某君新認識一網友。
當問及年齡時,他的網友說:
“我的年齡是個2位數,我比兒子大27歲,
如果把我的年齡的兩位數字交換位置,剛好就是我兒子的年齡”

請你計算:網友的年齡一共有多少種可能情況?

提示:30歲就是其中一種可能哦.

請填寫表示可能情況的種數。

注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。

答案:7

程式碼:

#include <iostream>
using namespace std;

int main()
{
	int ans=0;
	for(int i=0;i<=9; i++)
		for(int j=0; j<=9;j++)
			if( (i*10+j)-(j*10+i)==27 )
			ans++;
	cout<<ans;
	return 0;
}

2.生日蠟燭

某君從某年開始每年都舉辦一次生日party,並且每次都要吹熄與年齡相同根數的蠟燭。

現在算起來,他一共吹熄了236根蠟燭。


請問,他從多少歲開始過生日party的?

請填寫他開始過生日party的年齡數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。

答案:26

程式碼:

#include <iostream>
using namespace std;

int main()
{
	int ans=0;
	for(int i=1;i<=99; i++)
		for(int j=1; j<=50;j++)
			if( (i+i+j)*(j+1)/2 == 236 )
			{ans =i; break;}
	cout<<ans;
	return 0;
}


3.方格填數

如下的10個格子


填入0~9的數字。要求:連續的兩個數字不能相鄰。
(左右、上下、對角都算相鄰)

一共有多少種可能的填數方案?

請填寫表示方案數目的整數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字

答案:1580

程式碼:
#include <iostream>
#include <cmath>
using namespace std;

int a[10]={0,1,2,3,4,5,6,7,8,9};
int ans=0;
void swap(int a1, int b)
{
	int t = a[a1];
	a[a1] = a[b];
	a[b] =t ;
}
void fun (int x)
{
	if(x==10)
	{
		if(	abs(a[0]-a[1])!=1 && abs(a[0]-a[4])!=1 && abs(a[0]-a[3])!=1	&& abs(a[0]-a[5])!=1
	  	 && abs(a[1]-a[2])!=1 && abs(a[1]-a[4])!=1 && abs(a[1]-a[5])!=1 && abs(a[1]-a[6])!=1	
		 && abs(a[2]-a[5])!=1 && abs(a[2]-a[6])!=1	
		 && abs(a[3]-a[4])!=1 && abs(a[3]-a[7])!=1 && abs(a[3]-a[8])!=1
		 && abs(a[4]-a[5])!=1 && abs(a[4]-a[7])!=1 && abs(a[4]-a[8])!=1 && abs(a[4]-a[9])!=1
		 && abs(a[5]-a[6])!=1 && abs(a[5]-a[8])!=1 && abs(a[5]-a[9])!=1
		 && abs(a[6]-a[9])!=1
		 && abs(a[7]-a[8])!=1
		 && abs(a[8]-a[9])!=1
		)
		ans++;
	}
	for(int i=x; i<10; i++)
	{
		swap(x,i);
		fun(x+1);
		swap(x,i);
	}
}
int main()
{
	fun(0);
	cout<<ans;
	return 0;
}

4.快速排序

排序在各種場合經常被用到。
快速排序是十分常用的高效率的演算法。

其思想是:先選一個“標尺”,
用它把整個佇列過一遍篩子,
以保證:其左邊的元素都不大於它,其右邊的元素都不小於它。

這樣,排序問題就被分割為兩個子區間。
再分別對子區間排序就可以了。

下面的程式碼是一種實現,請分析並填寫劃線部分缺少的程式碼。

#include <stdio.h>

void swap(int a[], int i, int j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}

int partition(int a[], int p, int r)
{
    int i = p;
    int j = r + 1;
    int x = a[p];
    while(1){
        while(i<r && a[++i]<x);
        while(a[--j]>x);
        if(i>=j) break;
        swap(a,i,j);
    }
______________________;
    return j;
}

void quicksort(int a[], int p, int r)
{
    if(p<r){
        int q = partition(a,p,r);
        quicksort(a,p,q-1);
        quicksort(a,q+1,r);
    }
}
   
int main()
{
int i;
int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
int N = 12;

quicksort(a, 0, N-1);

for(i=0; i<N; i++) printf("%d ", a[i]);
printf("\n");

return 0;
}

注意:只填寫缺少的內容,不要書寫任何題面已有程式碼或說明性文字。

答案:swap(a,p,j);

5.消除尾一

下面的程式碼把一個整數的二進位制表示的最右邊的連續的1全部變成0
如果最後一位是0,則原數字保持不變。

如果採用程式碼中的測試資料,應該輸出:
00000000000000000000000001100111   00000000000000000000000001100000
00000000000000000000000000001100   00000000000000000000000000001100

請仔細閱讀程式,填寫劃線部分缺少的程式碼。

#include <stdio.h>
void f(int x)
{
int i;
for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
printf("   ");

x = _______________________;

for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
printf("\n");
}

int main()
{
f(103);
f(12);
return 0;
}

注意:只填寫缺少的內容,不要書寫任何題面已有程式碼或說明性文字。

答案:x&(x+1)

6.寒假作業

現在小學的數學題目也不是那麼好玩的。
看看這個寒假作業:

   
每個方塊代表1~13中的某一個數字,但不能重複。
比如:
 6  + 7 = 13
 9  - 8 = 1
 3  * 4 = 12
 10 / 2 = 5

以及: 
 7  + 6 = 13
 9  - 8 = 1
 3  * 4 = 12
 10 / 2 = 5

就算兩種解法。(加法,乘法交換律後算不同的方案)
 
你一共找到了多少種方案?

請填寫表示方案數目的整數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。

答案:64

程式碼:

#include<iostream>  
#include<algorithm>  
using namespace std;  
int c=0,a[14],v[14];  
void dfs(int s)  
{  
    int i;  
    if (s>3&&a[1]+a[2]!=a[3])  
     return ;  
    if (s>6&&a[4]-a[5]!=a[6])  
    return ;  
    if (s>9&&a[7]*a[8]!=a[9])  
     return ;  
    if (s>12&&a[12]*a[11]==a[10])  
    {  
        c++;  
        return ;  
    }  
    for (i=1;i<=13;i++)  
    {  
        if (!v[i])  
        {  
            v[i]=1;  
            a[s]=i;  
            if (s<13)  
             dfs(s+1);  
             v[i]=0;  
        }  
    }  
}  
int main()  
{  
    dfs(1);  
    cout<<c;  
    return 0;  
}  

7.剪郵票

如圖, 有12張連在一起的12生肖的郵票。


現在你要從中剪下5張來,要求必須是連著的。
(僅僅連線一個角不算相連)

比如圖2,圖3中,粉紅色所示部分就是合格的剪取。



請你計算,一共有多少種不同的剪取方法。

請填寫表示方案數目的整數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。

程式碼:

#include <iostream>
using namespace std;

int i1, i2, i3, i4, i5;
int visited[13]={1,0,0,1,1,1,1,0,1,1,1,1,1};

bool dfs(int s, int e)
{
	if(s==e)
		return true;
	if(visited[s]!=0)
		return false;
	visited[s]=1;
	if(s-4>=1)	if(dfs(s-4,e))	return true;
	if(s+4<=12)	if(dfs(s+4,e))	return true;
	if(s-1>=1&&s-1!=4&&s-1!=8)	if(dfs(s-1,e))	return true;
	if(s+1<=12&&s+1!=5&&s+1!=9)	if(dfs(s+1,e))	return true;
	return false;	
}
void init()
{
	visited[i1]=0;
	visited[i2]=0;
	visited[i3]=0;
	visited[i4]=0;
	visited[i5]=0;
}

bool judge()
{
	for(int i=0; i<13; i++)
		visited[i]=1;
	init();
	if(!dfs(i1,i2))	return false;
	init();
	if(!dfs(i1,i3))	return false;
	init();
	if(!dfs(i1,i4))	return false;
	init();
	if(!dfs(i1,i5))	return false;
	return true;
}

int main(int argc, const char * argv[])
{
	int ans=0;
	for(i1=1; i1<=8; i1++)
	{
		for(i2=i1+1; i2<=9; i2++)
		{
			for(i3=i2+1; i3<=10; i3++)
			{
				for(i4=i3+1; i4<=11; i4++)
				{
					for(i5=i4+1; i5<=12; i5++)
					{
						if(judge())	ans++;
						//cout<<i1<<"-"<<i2<<"-"<<i3<<"-"<<i4<<"-"<<i5<<endl;
					}
				}
			} 
		}
	} 
	cout<<ans;
    return 0;
}


8.四平方和

四平方和定理,又稱為拉格朗日定理:
每個正整數都可以表示為至多4個正整數的平方和。
如果把0包括進去,就正好可以表示為4個數的平方和。

比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
(^符號表示乘方的意思)

對於一個給定的正整數,可能存在多種平方和的表示法。
要求你對4個數排序:
0 <= a <= b <= c <= d
並對所有的可能表示法按 a,b,c,d 為聯合主鍵升序排列,最後輸出第一個表示法

程式輸入為一個正整數N (N<5000000)
要求輸出4個非負整數,按從小到大排序,中間用空格分開

例如,輸入:
5
則程式應該輸出:
0 0 1 2

再例如,輸入:
12
則程式應該輸出:
0 2 2 2

再例如,輸入:
773535
則程式應該輸出:
1 1 267 838

資源約定:
峰值記憶體消耗 < 256M
CPU消耗  < 3000ms

請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。

所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。

注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include <xxx>, 不能通過工程設定而省略常用標頭檔案。

提交時,注意選擇所期望的編譯器型別。


程式碼:

#include <iostream>
#include <cmath>
using namespace std;

int i1, i2, i3, i4;

int main(int argc, const char * argv[])
{
	double n;
	cin>>n; 
	int x1 =(int)sqrt(n/4)+1;
	int x2 =(int)sqrt(n/3)+1;
	int x3 =(int)sqrt(n/2)+1;
	double x4;	int x4_;
	
	for(i1=0;i1<=x1;i1++)
	{
		for(i2=i1;i2<=x2; i2++)
		{
			for(i3=i2; i3<=x3; i3++)
			{
				x4=(double)(n-i1*i1-i2*i2-i3*i3);
				x4_=(int)sqrt(x4);
				if(x4_*x4_ == (int)x4)
				{
					cout<<i1<<" "<<i2<<" "<<i3<<" "<<x4_<<endl;				
					return 0;
				}
					
			}
		}
	}
    return 0;
}



9.密碼脫落

X星球的考古學家發現了一批古代留下來的密碼。
這些密碼是由A、B、C、D 四種植物的種子串成的序列。
仔細分析發現,這些密碼串當初應該是前後對稱的(也就是我們說的映象串)。
由於年代久遠,其中許多種子脫落了,因而可能會失去映象的特徵。

你的任務是:
給定一個現在看到的密碼串,計算一下從當初的狀態,它要至少脫落多少個種子,才可能會變成現在的樣子。

輸入一行,表示現在看到的密碼串(長度不大於1000)
要求輸出一個正整數,表示至少脫落了多少個種子。

例如,輸入:
ABCBA
則程式應該輸出:
0

再例如,輸入:
ABDCDCBABC
則程式應該輸出:
3

資源約定:
峰值記憶體消耗 < 256M
CPU消耗  < 1000ms

請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。

所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。

注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include <xxx>, 不能通過工程設定而省略常用標頭檔案。

提交時,注意選擇所期望的編譯器型別。

程式碼:

#include <iostream>
using namespace std;

char s[1002];
int ans=0;
void fun()
{
	string x=s;
	int en= x.length()-1;
	int sa=0;
	while(sa<en)
	{
		if(s[sa]==s[en])
		{	sa++;	en--;
		}
		else
		{
			//左往右移動
			int	i,	j;
			for(i=sa+1; i<en; i++)
			{
				if(s[i]==s[en])
					break;
			} 
			for(j=en-1;	j>sa; j--)
			{	if(s[j]==s[sa])
					break;
			}
			if((i-sa)<(en-j))
			{
				ans+=i-sa;
				sa=i;
			}
			else
			{
				ans+=en-j;
				en=j;
			}
		}
	}
	cout<<ans<<endl;
}

int main(int argc, const char * argv[])
{
	cin>>s;
	fun();
    return 0;
}

10.最大比例

X星球的某個大獎賽設了M級獎勵。每個級別的獎金是一個正整數。
並且,相鄰的兩個級別間的比例是個固定值。
也就是說:所有級別的獎金數構成了一個等比數列。比如:
16,24,36,54
其等比值為:3/2

現在,我們隨機調查了一些獲獎者的獎金數。
請你據此推算可能的最大的等比值。

輸入格式:
第一行為數字 N (0<N<100),表示接下的一行包含N個正整數
第二行N個正整數Xi(Xi<1 000 000 000 000),用空格分開。每個整數表示調查到的某人的獎金數額

要求輸出:
一個形如A/B的分數,要求A、B互質。表示可能的最大比例係數

測試資料保證了輸入格式正確,並且最大比例是存在的。

例如,輸入:
3
1250 200 32

程式應該輸出:
25/4

再例如,輸入:
4
3125 32 32 200

程式應該輸出:
5/2

再例如,輸入:
3
549755813888 524288 2

程式應該輸出:
4/1

資源約定:
峰值記憶體消耗 < 256M
CPU消耗  < 3000ms

請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。

所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。

注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include <xxx>, 不能通過工程設定而省略常用標頭檔案。

提交時,注意選擇所期望的編譯器型別。

程式碼:

#include <iostream>
#include <algorithm>
using namespace std;

long long num[101];
int son[101];
int mom[101];
int n;

void bubble_sort() 
{
	int i, now, last=n-1;
	while(last>0)
	{
		for(i=now=0; i<last; i++)
		{
			if(num[i]>num[i+1])
			{
				long long t=num[i];
				num[i]=num[i+1];
				num[i+1]=t;
				now =i;
			}
		}
		last=now;
	}
}

int fun1(long long x1, long long x2)
{
	if(x1%x2 == 0)
		return x2;
	else
		return fun1(x2,x1%x2);
}
int fun2(long long x1, long long x2)
{
	if(x2<x1)
	{
		long long t =x2;
		x2=x1;
		x1=t;
	} 
	if(x2/x1 == x1)
		return x1;
	else
		return fun2(x2/x1,x1);
}
02
void main_fun()
{
	bubble_sort();
	int count=0;
	for(int i=0; i<n-1; i++)//獲得每一項的倍數 
	{
		if(num[i]!=num[i+1])
		{
			int t=fun1(num[i+1],num[i]);

			son[count]=num[i+1]/t;
			mom[count]=num[i]/t;
			count++;
		}
	}
	//
	for(int i=0; i<count-1; i++)	
	{
		son[i+1]=fun2(son[i],son[i+1]);
		mom[i+1]=fun2(mom[i],mom[i+1]);
	}
	cout<<son[count-1]<<"/"<<mom[count-1];
}


int main(int argc, const char * argv[])
{
	cin>>n;
	for(int i=0; i<n; i++)
		cin>>num[i];
	
	main_fun();
	
    return 0;
}