藍橋杯之暴力破解、枚舉

美國數學家維納(N.Wiener)智力早熟,11歲就上了大學。
他曾在1935~1936年應邀來中國清華大學講學。
一次,他參加某個重要會議,年輕的臉孔引人注目。
於是有人詢問他的年齡,他回答說:
“我年齡的立方是個4位數。我年齡的4次方是個6位數。這10個數字正好包含了從0到9這10個數字,每個都恰好出現1次。”
請你推算一下,他當時到底有多年輕。


思路:
通過暴力破解的方法,我們可以找到年齡的大概範圍,10^3=1000,30^4=8100
代碼:


#include<stdio.h>
#include<math.h>

int main(){
	for(int i=10;i<=30;i++){
		printf("%d= %.0f %.0f\n",i,pow(i,3),pow(i,4));
	}
}

通過觀察,我們發現18即爲正確答案。
注意,pow(x,y)的返回值爲double


------------------------------------------------


古羅馬帝國開創了輝煌的人類文明,但他們的數字表示法的確有些繁瑣,尤其在表示大數的時候,現在看起來簡直不能忍受,所以在現代很少使用了。
之所以這樣,不是因爲發明表示法的人的智力的問題,而是因爲一個宗教的原因,當時的宗教禁止在數字中出現0的概念!
羅馬數字的表示主要依賴以下幾個基本符號:


I --> 1
V --> 5
X --> 10
L --> 50
C --> 100
D --> 500
M --> 1000


這裏,我們只介紹一下1000以內的數字的表示法。
單個符號重複多少次,就表示多少倍。最多重複3次。
比如:CCC表示300  XX表示20,但150並不用LLL表示,這個規則僅適用於I X C M。


如果相鄰級別的大單位在右,小單位在左,表示大單位中扣除小單位。
比如:IX表示9  IV表示4  XL表示40 
49 = XLIX
    
更多的示例參見下表,你找到規律了嗎?    
I = 1 
II = 2
III = 3
IV = 4
V = 5
VI = 6
VII = 7
VIII = 8
IX = 9 
X = 10
XI = 11
XII = 12
XIII = 13
XIV = 14
XV = 15
XVI = 16
XVII = 17
XVIII = 18
XIX = 19
XX = 20
XXI = 21
XXII = 22
XXIX = 29
XXX = 30
XXXIV = 34
XXXV = 35
XXXIX = 39
XL = 40
L = 50
LI = 51
LV = 55
LX = 60
LXV = 65
LXXX = 80
XC = 90
XCIII = 93
XCV = 95
XCVIII = 98
XCIX = 99
C = 100
CC = 200
CCC = 300
CD = 400
D = 500
DC = 600
DCC = 700
DCCC = 800
CM = 900
CMXCIX = 999


本題目的要求是:請編寫程序,由用戶輸入若干個羅馬數字串,程序輸出對應的十進制表示。


輸入格式是:第一行是整數n,表示接下來有n個羅馬數字(n<100)。
以後每行一個羅馬數字。羅馬數字大小不超過999。
要求程序輸出n行,就是羅馬數字對應的十進制數據。


例如,用戶輸入:
3
LXXX
XCIII
DCCII


則程序應該輸出:
80
93
702


思路:本題有一個很大的突破點,即如何表示右邊比,仔細觀察,你會發現赭紅情況的數字只有那麼幾個,即:4、9、40、90、400、900,因此,不妨使用枚舉的方法進行排除。我們先對每個字母表示原來的數字進行累加,最後減去多加的部分,就可以得到正確答案。


C語言定義字符串:char s[];
C語言求字串:strstr(str1,str2);返回str1中首次出現str2的位置。


代碼:
#include<stdio.h>
#include<string.h>


int romeNum(char s[]);
int main(){
	int n;
	scanf("%d",&n);
	while(n--){
		char str[6];
		scanf("%s",str);
		printf("%d\n",romeNum(str));
	}
} 


int romeNum(char s[]){
	int sum;
	for(int i=0;i<strlen(s);i++){
		char c = s[i];
		if(c=='I') sum+=1;
		if(c=='V') sum+=5;
		if(c=='X') sum+=10;
		if(c=='L') sum+=50;
		if(c=='C') sum+=100;
		if(c=='D') sum+=500;
		if(c=='M') sum+=1000;
	}
	if(strstr(s,"IV")!=NULL) sum-=2;
	if(strstr(s,"IX")!=NULL) sum-=2;
	if(strstr(s,"XL")!=NULL) sum-=20;
	if(strstr(s,"XC")!=NULL) sum-=20;
	if(strstr(s,"CD")!=NULL) sum-=200;
	if(strstr(s,"CM")!=NULL) sum-=200;
	return sum;
}

------------------------------------------------


小明最近在教鄰居家的小朋友小學奧數,而最近正好講述到了三階幻方這個部分。
三階幻方指的是將1~9不重複的填入一個3*3的矩陣當中,使得每一行、每一列和每一條對角線的和都是相同的。
三階幻方又被稱作九宮格,在小學奧數裏有一句非常有名的口訣:
“二四爲肩,六八爲足,左三右七,戴九履一,五居其中”,
通過這樣的一句口訣就能夠非常完美的構造出一個九宮格來。
4 9 2
3 5 7
8 1 6
有意思的是,所有的三階幻方,都可以通過這樣一個九宮格進行若干鏡像和旋轉操作之後得到。
現在小明準備將一個三階幻方(不一定是上圖中的那個)中的一些數抹掉,交給鄰居家的小朋友來進行還原,並且希望她能夠判斷出究竟是不是隻有一個解。

而你呢,也被小明交付了同樣的任務,但是不同的是,你需要寫一個程序~


輸入格式:
輸入僅包含單組測試數據。
每組測試數據爲一個3*3的矩陣,其中爲0的部分表示被小明抹去的部分。
對於100%的數據,滿足給出的矩陣至少能還原出一組可行的三階幻方。


輸出格式:
如果僅能還原出一組可行的三階幻方,則將其輸出,否則輸出“Too Many”(不包含引號)。


樣例輸入
0 7 2
0 5 0
0 3 0


樣例輸出
6 7 2
1 5 9
8 3 4


思路:
因爲三階幻方經過變換,最終只有8種結果,所以,我們採用枚舉的方式,首先將8中可能性都寫出來,然後將輸入的數據與每一種可能進行對比。


代碼:
#include<stdio.h>

int isTrue(int b[]);
int main(){
	int a[9];
	for(int i=0;i<9;i++){
		scanf("%d",&a[i]);
	}
	isTrue(a);
	return 0;
}


int isTrue(int b[]){
	int a[8][9]={
		{4,9,2,3,5,7,8,1,6},
		{8,3,4,1,5,9,6,7,2},
		{6,1,8,7,5,3,2,9,4},
		{2,9,4,7,5,3,1,8,6},
		{8,1,6,3,5,7,4,9,2},
		{6,7,2,1,5,9,8,3,4},
		{2,9,4,7,5,3,6,1,8},
		{1,8,6,7,5,3,2,9,4}
	};	
	
	printf("\n");
	
	for(int i=0;i<8;i++){
		int flag=1;
		for(int j=0;j<9;j++){
			if(b[j]==0) continue;
			if(a[i][j]!=b[j]) flag=0;
		}
		if(flag==1){
			printf("%d %d %d\n%d %d %d\n%d %d %d\n",a[i][0],a[i][1],a[i][2],a[i][3],a[i][4],a[i][5],a[i][6],a[i][7],a[i][8],a[i][9]);
			break;
		}		
	}
	
}


------------------------------------------------



魔方可以對它的6個面自由旋轉。


我們來操作一個2階魔方(如圖1所示):
爲了描述方便,我們爲它建立了座標系。


各個面的初始狀態如下:
x軸正向:綠
x軸反向:藍
y軸正向:紅
y軸反向:橙
z軸正向:白
z軸反向:黃


假設我們規定,只能對該魔方進行3種操作。分別標記爲:
x 表示在x軸正向做順時針旋轉
y 表示在y軸正向做順時針旋轉
z 表示在z軸正向做順時針旋轉


xyz 則表示順序執行x,y,z 3個操作


題目的要求是:
用戶從鍵盤輸入一個串,表示操作序列。
程序輸出:距離我們最近的那個小方塊的3個面的顏色。
順序是:x面,y面,z面。


例如:在初始狀態,應該輸出:
綠紅白


初始狀態下,如果用戶輸入:
x
則應該輸出:
綠白橙


初始狀態下,如果用戶輸入:
zyx
則應該輸出:
紅白綠


------------------------------------------------


【信用卡號的驗證】


當你輸入信用卡號碼的時候,有沒有擔心輸錯了而造成損失呢?其實可以不必這麼擔心,因爲並不是一個隨便的信用卡號碼都是合法的,它必須通過Luhn算法來驗證通過。
該校驗的過程:
1、從卡號最後一位數字開始,逆向將奇數位(1、3、5等等)相加。
2、從卡號最後一位數字開始,逆向將偶數位數字,先乘以2(如果乘積爲兩位數,則將其減去9),再求和。
3、將奇數位總和加上偶數位總和,結果應該可以被10整除。
例如,卡號是:5432123456788881


則,奇數位和=35
偶數位乘以2(有些要減去9)的結果:1 6 2 6 1 5 7 7,求和=35。
最後35+35=70 可以被10整除,認定校驗通過。


請編寫一個程序,從鍵盤輸入卡號,然後判斷是否校驗通過。通過顯示:“成功”,否則顯示“失敗”。
比如,用戶輸入:356827027232780
程序輸出:成功


【參考測試用例】
356406010024817     成功
358973017867744     成功
356827027232781     失敗
306406010024817     失敗
358973017867754     失敗


思路:
這道題很簡單,直接一次取模相加就好,有一個坑,就是不能使用int型來保存輸入的數據,會越界。


代碼:
#include<stdio.h>

void isTrue(long long n);
int main(){
	long long n;
	scanf("%lld",&n);
	isTrue(n);
	return 0;
} 
void isTrue(long long n){
	int flag=1,sum=0;
	while(n){
		if(flag){
			sum+=n%10;
			n=n/10;
			flag=0;
			
		}else{
			int t=(n%10)*2;
			if(t>9) t=t-9;
			sum+=t;
			n=n/10;
			flag=1;
		}
	}
	
	if(sum%10==0){
		printf("成功");
	}else{
		printf("失敗");
	}
}

發佈了36 篇原創文章 · 獲贊 73 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章