美國數學家維納(N.Wiener)智力早熟,11歲就上了大學。他曾在1935~1936年應邀來中國清華大學講學。一次,他參加某個重要會議,年輕的臉孔引人注目。因而有人詢問他的年齡,他回答說:「我年齡的立方是個4位數。我年齡的4次方是個6位數。這10個數字正好包含了從0到9這10個數字,每一個都剛好出現1次。」ios
請你推算一下,他當時到底有多年輕。經過瀏覽器,直接提交他那時的年齡數字。注意:不要提交解答過程,或其它的說明文字。c++
代碼:算法
#include<iostream> using namespace std; int main(){ for(int i=10;i<50;i++){ int _3=i*i*i; int _4=_3*i; if(_3>=1000&&_3<10000&&_4>=100000&&_4<1000000){ printf("%d %d %d\n",i,_3,_4); } } return 0; } //輸出結果爲: //18 5832 104976 //19 6859 130321 //20 8000 160000 //21 9261 194481
因爲這是填空題,只要能算出結果便可,先把可能的結果輸出,根據判斷年齡爲18的時候,0-9每一個數字只出現1次符合條件。編程
小明是個急性子,上小學的時候常常把老師寫在黑板上的題目抄錯了。數組
有一次,老師出的題目是:36 x 495 = ?瀏覽器
他卻給抄成了:396 x 45 = ?函數
但結果卻很戲劇性,他的答案居然是對的!!spa
由於 36 * 495 = 396 * 45 = 17820設計
相似這樣的巧合狀況可能還有不少,好比:27 * 594 = 297 * 54code
假設 a b c d e 表明1~9不一樣的5個數字(注意是各不相同的數字,且不含0)
能知足形如: ab * cde = adb * ce 這樣的算式一共有多少種呢?
請你利用計算機的優點尋找全部的可能,並回答不一樣算式的種類數。
知足乘法交換律的算式計爲不一樣的種類,因此答案確定是個偶數。
答案直接經過瀏覽器提交。
注意:只提交一個表示最終統計種類數的數字,不要提交解答過程或其它多餘的內容。
代碼:
暴力枚舉列出全部可能結果
#include<iostream> using namespace std; int main(){ int ans=0; for(int a=1;a<=9;a++){ for(int b=1;b<=9;b++){ if(b!=a){//各個數字不相同判斷 for(int c=1;c<=9;c++){ if(c!=a&&c!=b){//各個數字不相同判斷 for(int d=1;d<=9;d++){ if(d!=a&&d!=b&&d!=c){//各個數字不相同判斷 for(int e=1;e<=9;e++){ if(e!=a&&e!=b&&e!=c&&e!=d){//各個數字不相同判斷 if((a*10+b)*(c*100+d*10+e)==(a*100+d*10+b)*(c*10+e)){ ans++; } } } } } } } } } } cout<<ans<<endl; return 0; } //輸出結果:142
暴力到沒朋友
填空題應第一考慮可否暴力枚舉,簡單粗暴。
小明參加了學校的趣味運動會,其中的一個項目是:跳格子。
地上畫着一些格子,每一個格子裏寫一個字,以下所示:
比賽時,先站在左上角的寫着「從」字的格子裏,能夠橫向或縱向跳到相鄰的格子裏,但不能跳到對角的格子或其它位置。一直要跳到「華」字結束。
要求跳過的路線恰好構成「從我作起振興中華」這句話。
請你幫助小明算一算他一共有多少種可能的跳躍路線呢?
答案是一個整數,請經過瀏覽器直接提交該數字。
注意:不要提交解答過程,或其它輔助說明類的內容。
代碼:
簡單理解就是從「從」到「華」有多少條路能夠走
#include<iostream> using namespace std; bool vis[5][5]; int f(int x,int y){ if(x==3&&y==4) //已經到"華"只有一種 return 1; else if(x==3) //已經到最後一行,只能往右走 return f(x,y+1); else if(y==4) //已經到最後一列,只能往下走 return f(x+1,y); else return f(x+1,y)+f(x,y+1); } int main(){ cout<<f(0,0); return 0; } //輸出結果:35
遞歸的方法:找重複、找狀態、找出口
幻方是把一些數字填在方格中,使得行、列、兩條對角線的數字之和都相等。
歐洲最著名的幻方是德國數學家、畫家迪勒創做的版畫《憂鬱》中給出的一個4階幻方。
他把1,2,3,...16 這16個數字填寫在4 x 4的方格中。
如圖所示,即:
表中有些數字已經顯露出來,還有些用?和*代替。
請你計算出? 和 * 所表明的數字。並把 * 所表明的數字做爲本題答案提交。
答案是一個整數,請經過瀏覽器直接提交該數字。
注意:不要提交解答過程,或其它輔助說明類的內容。
代碼:
已經使用的數字:1,9,11,13,16
未使用的數字:2,3,4,5,6,7,8,10,12,14,15
由於每一個空只能填一個數字,每一個數字只能填一次,故使用暴力法,求未使用的數字進行全排列,即它們可能組成的各類順序,依次填入方格中進行判斷,當知足條件時返回便可。
在c++中有相應的全排列公式next_permutation(),其它語言須要手動實現。
#include<iostream> #include<vector> #include<algorithm> using namespace std; int a[]={2,3,4,5,6,7,8,10,12,14}; void check(vector<int> arr){ int r1=16+arr[0]+arr[1]+13; int r2=arr[2]+arr[3]+11+arr[4]; int r3=9+arr[5]+arr[6]+arr[7]; int r4=arr[8]+15+arr[9]+1; int c1=16+arr[2]+9+arr[8]; int c2=arr[0]+arr[3]+arr[5]+15; int c3=arr[1]+11+arr[6]+arr[9]; int c4=13+arr[4]+arr[7]+1; int l=16+arr[3]+arr[6]+1; int r=13+11+arr[5]+arr[8]; if(r1==r2&&r2==r3&&r3==r4&&r4==c1&&c1==c2&&c2==c3&&c3==c4&&c4==l&&l==r){ cout<<arr[7]<<endl; } } int main(){ vector<int> arr; for(int i=0;i<10;i++){ arr.push_back(a[i]); } do{ check(arr); }while(next_permutation(arr.begin(),arr.end())); return 0; }
咱們常常會用到求兩個整數的最大公約數和最小公倍數的功能。
下面的程序給出了一種算法。
函數 myfunc 接受兩個正整數a,b
通過運算後打印出 它們的最大公約數和最小公倍數。
此時,調用 myfunc(15,20)
將會輸出:
5
60
請分析代碼邏輯,並推測劃線處的代碼,經過網頁提交。
注意:僅把缺乏的代碼做爲答案,千萬不要填寫多餘的代碼、符號或說明文字!!
// 交換數值 void swap(int *a,int *b) { int temp; temp=*a; *a=*b; *b=temp; } void myfunc(int a, int b) //使用展轉相除法求最大公約數 { int m,n,r; if(a<b) swap(&a,&b); m=a;n=b;r=a%b; while(r!=0) { a=b;b=r; r=a%b; } printf("%d\n",b); // 最大公約數 printf("%d\n", ____________________________________); // 最小公倍數 } //已知最大公約數b時可使用公式 n*m/b a,b已經改變,n,m是a,b的拷貝故使用n,m. //答案:n*m/b
通常的排序有許多經典算法,如快速排序、希爾排序等。
但實際應用時,常常會或多或少有一些特殊的要求。咱們不必套用那些經典算法,能夠根據實際狀況創建更好的解法。
好比,對一個整型數組中的數字進行分類排序:
使得負數都靠左端,正數都靠右端,0在中部。注意問題的特色是:負數區域和正數區域內並不要求有序。能夠利用這個特色經過1次線性掃描就結束戰鬥!!
如下的程序實現了該目標。
其中x指向待排序的整型數組,len是數組的長度。
若是給定數組:
25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0
則排序後爲:
-3,-2,-16,-5,0,0,0,21,19,33,25,16,18,25
請分析代碼邏輯,並推測劃線處的代碼,經過網頁提交
注意:僅把缺乏的代碼做爲答案,千萬不要填寫多餘的代碼、符號或說明文字!!
void sort3p(int* x, int len) { int p = 0; int left = 0; int right = len-1; while(p<=right){ if(x[p]<0){ int t = x[left]; x[left] = x[p]; x[p] = t; left++; p++; }else if(x[p]>0){ int t = x[right]; x[right] = x[p]; x[p] = t; right--; } else{ p++; //填空位置 } } }
p 指向當前要判斷元素的下邊
left 指向元素的左邊都小於0,right指向元素的右邊都大於0。
問題描述
小張是軟件項目經理,他帶領3個開發組。工期緊,今天都在加班呢。爲鼓舞士氣,小張打算給每一個組發一袋核桃(據傳言能補腦)。他的要求是:
輸入格式
輸入包含三個正整數a, b, c,表示每一個組正在加班的人數,用空格分開(a,b,c<30)
輸出格式
輸出一個正整數,表示每袋核桃的數量。
樣例輸入1
2 4 5
樣例輸出1
20
樣例輸入2
3 1 1
樣例輸出2
3
代碼:
簡單理解就是要求這三個數的最小公倍數,使用暴力枚舉,最壞三者的最小公倍數爲a * b * c。
#include<iostream> using namespace std; int main(){ int a,b,c; cin>>a>>b>>c; for(int i=1;i<=a*b*c;i++){ if(i%a==0&&i%b==0&&i%c==0){ cout<<i<<endl; break; } } return 0; }
小明爲某機構設計了一個十字型的徽標(並不是紅十字會啊),以下所示:
..$$$$$$$$$$$$$.. ..$...........$.. $$$.$$$$$$$$$.$$$ $...$.......$...$ $.$$$.$$$$$.$$$.$ $.$...$...$...$.$ $.$.$$$.$.$$$.$.$ $.$.$...$...$.$.$ $.$.$.$$$$$.$.$.$ $.$.$...$...$.$.$ $.$.$$$.$.$$$.$.$ $.$...$...$...$.$ $.$$$.$$$$$.$$$.$ $...$.......$...$ $$$.$$$$$$$$$.$$$ ..$...........$.. ..$$$$$$$$$$$$$..
對方同時也須要在電腦dos窗口中以字符的形式輸出該標誌,並能任意控制層數。
輸入1 ,則輸出
..$$$$$.. ..$...$.. $$$.$.$$$ $...$...$ $.$$$$$.$ $...$...$ $$$.$.$$$ ..$...$.. ..$$$$$..
輸入
一個正整數 n (n< 30) 表示要求打印圖形的層數。
輸出
對應包圍層數的該標誌。
樣例輸入
3
樣例輸出
..$$$$$$$$$$$$$.. ..$...........$.. $$$.$$$$$$$$$.$$$ $...$.......$...$ $.$$$.$$$$$.$$$.$ $.$...$...$...$.$ $.$.$$$.$.$$$.$.$ $.$.$...$...$.$.$ $.$.$.$$$$$.$.$.$ $.$.$...$...$.$.$ $.$.$$$.$.$$$.$.$ $.$...$...$...$.$ $.$$$.$$$$$.$$$.$ $...$.......$...$ $$$.$$$$$$$$$.$$$ ..$...........$.. ..$$$$$$$$$$$$$..
代碼:
假設最外層爲第一層
n=3時
爲17 * 17的方格;第一行$個數13
n=2時
爲13 * 13的方格; 第一行$個數9
n=1時
爲 9 * 9的方格; 第一行$個數5
L表示左側邊界爲0,R表示右側邊界爲9+4*(n-1)-1 (下標從0開始R的下標須要減1)
寫死後,只輸出最外一層
#include<iostream> using namespace std; char arr[9+4*28][9+4*28]; int N; //一共有幾層 int L=0; //最外層左邊界下標 int R; //最外層右邊界下標 void printAll(int left,int right){ for(int i=left;i<=right;i++){ for(int j=left;j<=right;j++){ if(arr[i][j]!='$') arr[i][j]='.'; cout<<arr[i][j]; } cout<<endl; } } int main(){ cin>>N; cout<<N<<endl; R=9+4*(N-1)-1; //求出最外層右邊界下標 //處理第一行和最後一行 for(int i=2;i<=R-2;i++){ arr[0][i]='$'; arr[R][i]='$'; } //處理第二行和倒數第二行 arr[1][2]='$'; arr[1][R-2]='$'; arr[R-1][2]='$'; arr[R-1][R-2]='$'; //處理第三行和倒數第三行 arr[2][0]='$'; arr[2][1]='$'; arr[2][2]='$'; arr[2][R]='$'; arr[2][R-1]='$'; arr[2][R-2]='$'; arr[R-2][0]='$'; arr[R-2][1]='$'; arr[R-2][2]='$'; arr[R-2][R]='$'; arr[R-2][R-1]='$'; arr[R-2][R-2]='$'; //處理兩邊 for(int i=3;i<=R-3;i++){ arr[i][0]='$'; arr[i][R]='$'; } printAll(L,R); return 0; } 輸入: 3 輸出: ..$$$$$$$$$$$$$.. ..$...........$.. $$$...........$$$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $$$...........$$$ ..$...........$.. ..$$$$$$$$$$$$$.. 輸入: 1 輸出: ..$$$$$.. ..$...$.. $$$...$$$ $.......$ $.......$ $.......$ $$$...$$$ ..$...$.. ..$$$$$..
而後找規律,發現每層只是左右邊界不一樣L每次加2,R每次減2,故單獨寫一個方法輸出第n層的圖像
#include<iostream> using namespace std; char arr[9+4*28][9+4*28]; int N; //一共有幾層 int L=0; //最外層左邊界下標 int R; //最外層右邊界下標 void printAll(int left,int right){ for(int i=left;i<=right;i++){ for(int j=left;j<=right;j++){ if(arr[i][j]!='$') arr[i][j]='.'; cout<<arr[i][j]; } cout<<endl; } } void dealN(int n){ int l,r; //當前層的左右邊界,由於時方格,l也表示上邊界,r也表示下邊界 l=2*(N-n); r=R-2*(N-n); //處理第一行和最後一行 for(int i=l+2;i<=r-2;i++){ arr[l][i]='$'; arr[r][i]='$'; } //處理第二行和倒數第二行 arr[l+1][l+2]='$'; arr[l+1][r-2]='$'; arr[r-1][l+2]='$'; arr[r-1][r-2]='$'; //處理第三行和倒數第三行 arr[l+2][l]='$'; arr[l+2][l+1]='$'; arr[l+2][l+2]='$'; arr[l+2][r]='$'; arr[l+2][r-1]='$'; arr[l+2][r-2]='$'; arr[r-2][l]='$'; arr[r-2][l+1]='$'; arr[r-2][l+2]='$'; arr[r-2][r]='$'; arr[r-2][r-1]='$'; arr[r-2][r-2]='$'; //處理兩邊 for(int i=l+3;i<=r-3;i++){ arr[i][l]='$'; arr[i][r]='$'; } } int main(){ cin>>N; R=9+4*(N-1)-1; //求出最外層右邊界下標 for(int i=N;i>0;i--){ dealN(i); } //最後處理中間十字 for(int i=2*N;i<2*N+5;i++){ arr[2*N+2][i]='$'; arr[i][2*N+2]='$'; } printAll(L,R); return 0; } 輸入3時 ..$$$$$$$$$$$$$.. ..$...........$.. $$$.$$$$$$$$$.$$$ $...$.......$...$ $.$$$.$$$$$.$$$.$ $.$...$...$...$.$ $.$.$$$.$.$$$.$.$ $.$.$...$...$.$.$ $.$.$.$$$$$.$.$.$ $.$.$...$...$.$.$ $.$.$$$.$.$$$.$.$ $.$...$...$...$.$ $.$$$.$$$$$.$$$.$ $...$.......$...$ $$$.$$$$$$$$$.$$$ ..$...........$.. ..$$$$$$$$$$$$$..
問題描述
100 能夠表示爲帶分數的形式:100 = 3 + 69258 / 714。
還能夠表示爲:100 = 82 + 3546 / 197。
注意特徵:帶分數中,數字1~9分別出現且只出現一次(不包含0)。
相似這樣的帶分數,100 有 11 種表示法。
輸入格式
從標準輸入讀入一個正整數N (N<1000*1000)
輸出格式
程序輸出該數字用數碼1~9不重複不遺漏地組成帶分數表示的所有種數。
注意:不要求輸出每一個表示,只統計有多少表示法!
樣例輸入1
100
樣例輸出1
11
樣例輸入2
105
樣例輸出2
6
分析:
生成1-9這9個數字的全排列,先在可能的位置插入「+」號,而後在可能的位置插入「/」號,再驗證等式。
#include<iostream> #include<algorithm> #include<string> using namespace std; int main(){ int n,ans=0; cin>>n; string s="123456789"; do{ for(int i=1;i<=7;i++){ // i:"+"前串的長度 string a=s.substr(0,i); int inta=atoi(a.c_str()); // string 轉換 int if(inta>=n) break; for(int j=1;j<=9-i-1;j++){ // j: "+"和"/"之間串的長度 string b=s.substr(i,j); string c=s.substr(i+j);// "/"後面的串 int intb=atoi(b.c_str()); int intc=atoi(c.c_str()); if(intb%intc==0&&inta+intb/intc==n) ans++; } } }while(next_permutation(s.begin(),s.end())); cout<<ans<<endl; return 0; }
結果時正確的,可是運行超時,反覆使用substr()
函數會消耗大量時間,須要對代碼進行改進。
#include<iostream> #include<algorithm> #include<string> using namespace std; //本身實現一個函數,經過從pos截取len長度的字符串 int parse(const char *arr,int pos,int len){ int ans=0; int t=1; for(int i=pos+len-1;i>=pos;i--){ ans+=(arr[i]-'0')*t; t*=10; } return ans; } int main(){ int n,ans=0; cin>>n; string s="123456789"; do{ const char *str=s.c_str(); for(int i=1;i<=7;i++){ // i:"+"前串的長度 // string a=s.substr(0,i); // int inta=atoi(a.c_str()); // string 轉換 int int inta=parse(str,0,i); if(inta>=n) break; for(int j=1;j<=9-i-1;j++){ // j: "+"和"/"之間串的長度 // string b=s.substr(i,j); // string c=s.substr(i+j);// "/"後面的串 // int intb=atoi(b.c_str()); // int intc=atoi(c.c_str()); int intb=parse(str,i,j); int intc=parse(str,i+j,9-i-j); if(intb%intc==0&&inta+intb/intc==n) ans++; } } }while(next_permutation(s.begin(),s.end())); cout<<ans<<endl; return 0; } //完美,測評經過。
以下圖所示,3 x 3 的格子中填寫了一些整數。
+--*--+--+ |10* 1|52| +--****--+ |20|30* 1| *******--+ | 1| 2| 3| +--+--+--+
咱們沿着圖中的星號線剪開,獲得兩個部分,每一個部分的數字和都是60。
本題的要求就是請你編程斷定:對給定的m x n 的格子中的整數,是否能夠分割爲兩個部分,使得這兩個區域的數字和相等。
若是存在多種解答,請輸出包含左上角格子的那個區域包含的格子的最小數目。
若是沒法分割,則輸出 0。
輸入格式
程序先讀入兩個整數 m n 用空格分割 (m,n<10)。
表示表格的寬度和高度。
接下來是n行,每行m個正整數,用空格分開。每一個整數不大於10000。
輸出格式
輸出一個整數,表示在全部解中,包含左上角的分割區可能包含的最小的格子數目。
樣例輸入1
3 3
10 1 52
20 30 1
1 2 3
樣例輸出1
3
樣例輸入2
4 3
1 1 1 1
1 30 80 2
1 1 1 100
樣例輸出2
10
#include<iostream> #include<algorithm> using namespace std; int m,n,total; int g[10][10],ans=100; bool vis[10][10]; int dx[]={1, 0,-1,0}; int dy[]={0,-1, 0,1}; bool in(int x,int y){ //判斷該位置是否合法 if(x>=0&&x<=n-1&&y>=0&&y<=m-1){ return true; }else{ return false; } } void f(int x,int y,int sum,int cnt){ // printf("(%d,%d)sum=%d,cnt=%d\n",x,y,sum,cnt); if(sum>total/2) return; if(sum==total/2){ ans=min(ans,cnt); return; } vis[x][y]=true; for(int i=0;i<4;i++){ int tx=x+dx[i]; int ty=y+dy[i]; if(in(tx,ty)&&!vis[tx][ty]){ f(tx,ty,sum+g[x][y],cnt+1); } } vis[x][y]=false; } int main(){ cin>>m>>n; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ cin>>g[i][j]; total+=g[i][j]; //求出全部元素的和 } } f(0,0,0,0); cout<<ans<<endl; return 0; }
上面的代碼能夠經過藍橋杯練習系統,但在有些特殊的狀況會執行錯誤,例如:
1 1
1 2
應輸出3,運行結果是0,表示沒法分割。