SuperPrime Rib
題目(簡述):
找出某一長度的超級素數。所謂的超級素數,例如7331:其中7331是素數,733是素數,73是素數,7是素數。即每次從該數中去掉最後一位元後,依然是素數的素數,被稱為超級素數(superprime)。
分析:
判斷一個數是不是超級素數,我們需要判斷n次,n為這個數的位元。為了使程式更快,我們應該首先判斷最高位是不是素數,然後判斷最高兩位是不是素數……直到判斷到這個數本身是不是素數。其次,我們並不需要遍曆所有的n位元,因為很多數直接就可以排除掉:除了最高位,其他任何位上有偶數的排除,1開頭的數排除,至於為什麼,原因很簡單,大家可以自己思考。這樣之後,我們其實可以產生這樣的數,而不是遍曆。產生這樣的數的時候,注意要按照從小到大的順序。下面是代碼實現。
代碼:
Executing... Test 1: TEST OK [0.000 secs, 3048 KB] Test 2: TEST OK [0.000 secs, 3048 KB] Test 3: TEST OK [0.000 secs, 3048 KB] Test 4: TEST OK [0.000 secs, 3048 KB] Test 5: TEST OK [0.000 secs, 3048 KB]/*ID:haxc_xc1PROG:sprimeLANG:C++*/#include <stdio.h>#include <stdlib.h>#include <math.h>int n;bool prime(int num){bool ret=true;int i;for(i=2;i<=sqrt(num);i++){if(num%i==0){ret=false;break;}}return ret;}void deal(int num,int k){if(k==n){if(prime(num)) //搜尋到k位的時候,如果滿足條件,則直接輸出{printf("%d\n",num);}}else{if(prime(num*10+1)) //如果這個數滿足,則向下搜尋{deal(num*10+1,k+1);}if(prime(num*10+3)){deal(num*10+3,k+1);}if(prime(num*10+5)){deal(num*10+5,k+1);}if(prime(num*10+7)){deal(num*10+7,k+1);}if(prime(num*10+9)){deal(num*10+9,k+1);}}}int main(void){freopen("sprime.in","r",stdin);freopen("sprime.out","w",stdout);scanf("%d",&n);deal(2,1);deal(3,1);deal(5,1);deal(7,1);return 0;}Checker Challenge
題目:
這個問題是8皇后問題的擴充,讀入一個數n,代表n*n的格子,求出所有的方案數,並且輸出前3種方案的具體內容。
分析:
筆者寫的第一個程式,是基於深度優先搜尋,沒有任何最佳化,n=13時運算逾時。後來看了若干別人的分析之後,瞭解到matrix67大牛的一個基於位元運算的演算法,深表佩服:具體連結:http://www.matrix67.com/blog/archives/266。具體內容裡面已經講述地很清楚了,也就不再贅述。代碼部分附上本人所寫的基於此思想的C語言的實現。另外,這個題還可以採用對稱的思想對其進行最佳化。
代碼(只輸出了所有方案的數量,沒有輸出前3個具體的方案):
#include <stdio.h>#include <stdlib.h>int n;unsigned upperlim;int result;void deal(unsigned row,unsigned ld,unsigned rd,int deep)//row代表列有衝突的,ld代表左斜對角線有衝突的,rd代表右斜對角線有衝突的。deep代表層數或者深度,都可以。{if(row!=upperlim)//還沒有放完{unsigned pos=upperlim & ~(row|ld|rd),p;while(pos){p=pos&(-pos); //p為右起第一個安全位元置pos=pos^p; //設定禁止位deal(row|p,(ld|p)>>1,(rd|p)<<1,deep+1);}}else{result++;}}int main(void){freopen("checker.in","r",stdin);freopen("checker.out","w",stdout);scanf("%d",&n);upperlim=(1<<n)-1; //upperlim的每一位都表示了該位置是否能夠放下deal(0,0,0,1);printf("%d\n",result);return 0;}