1. 程式人生 > 實用技巧 >HDU100題簡要題解(2040~2049)

HDU100題簡要題解(2040~2049)

Problem Description
古希臘數學家畢達哥拉斯在自然數研究中發現,220的所有真約數(即不是自身的約數)之和為:
1+2+4+5+10+11+20+22+44+55+110=284。
而284的所有真約數為1、2、4、71、 142,加起來恰好為220。人們對這樣的數感到很驚奇,並稱之為親和數。一般地講,如果兩個數中任何一個數都是另一個數的真約數之和,則這兩個數就是親和數。
你的任務就編寫一個程式,判斷給定的兩個數是否是親和數
Input
輸入資料第一行包含一個數M,接下有M行,每行一個例項,包含兩個整數A,B; 其中 0 <= A,B <= 600000 ;
Output
對於每個測試例項,如果A和B是親和數的話輸出YES,否則輸出NO。
Sample Input
2
220 284
100 200
Sample Output
YES
NO

求每個數的真約數和與另一個數進行比較就好了

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

int m;

int cal(int x) {
  int cnt = 0;
  for (int i = 1; i < x; i++) 
    if (x % i == 0) cnt += i;
  return cnt;
}

int main() {
  while (scanf("%d", &m) != EOF) {
    for (int i = 1; i <= m; i++) {
      int a, b;
      scanf("%d%d", &a, &b);
      int num1 = cal(a);
      int num2 = cal(b);
      if (a == num2 && b == num1) printf("YES\n");
      else printf("NO\n");
    } 
  }
  return 0;
}

Problem Description
有一樓梯共M級,剛開始時你在第一級,若每次只能跨上一級或二級,要走上第M級,共有多少種走法?
Input
輸入資料首先包含一個整數N,表示測試例項的個數,然後是N行資料,每行包含一個整數M(1<=M<=40),表示樓梯的級數。
Output
對於每個測試例項,請輸出不同走法的數量
Sample Input
2
2
3
Sample Output
1
2

十分經典的題目,到達第n個臺階可以從第n-1級臺階跨一級上來,也可以從第n-2級臺階跨兩級上來
所以我們很容易得到遞推公式a[n] = a[n - 1] + a[n - 2]
注意初始化a[2] = 1; a[3] = 2

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

int n, m, dp[41];

int main() {
  while (scanf("%d", &n) != EOF) {
    dp[2] = 1;
    dp[3] = 2;
    for (int i = 1; i <= n; i++) {
      scanf("%d", &m);
      for (int i = 4; i <= m; i++) dp[i] = dp[i - 1] + dp[i - 2];
      printf("%d\n", dp[m]);
    }
  }
  return 0;
}

Problem Description
你活的不容易,我活的不容易,他活的也不容易。不過,如果你看了下面的故事,就會知道,有位老漢比你還不容易。
重慶市郊黃泥板村的徐老漢(大號徐東海,簡稱XDH)這兩年辛辛苦苦養了不少羊,到了今年夏天,由於眾所周知的高溫乾旱,實在沒辦法解決牲畜的飲水問題,就決定把這些羊都趕到集市去賣。從黃泥板村到交易地點要經過N個收費站,按說這收費站和徐老漢沒什麼關係,但是事實卻令徐老漢欲哭無淚:
中間一堆廢話......這裡略過......
由於徐老漢沒錢,收費員就將他的羊拿走一半,看到老漢淚水漣漣,猶豫了一下,又還給老漢一隻。巧合的是,後面每過一個收費站,都是拿走當時羊的一半,然後退還一隻,等到老漢到達市場,就只剩下3只羊了。
你,當代有良知的青年,能幫忙算一下老漢最初有多少隻羊嗎?
Input
輸入資料第一行是一個整數N,下面由N行組成,每行包含一個整數a(0<a<=30),表示收費站的數量。
Output
對於每個測試例項,請輸出最初的羊的數量,每個測試例項的輸出佔一行。
Sample Input
2
1
2
Sample Output
4
6

和之前吃蟠桃一個樣子的,只是蟠桃是每次吃掉一半多一個,現在是羊每次拿走一半少一個
稍微做一下改動即可

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

int n, m, sum = 1;

int main() {
  while (scanf("%d", &n) != EOF) {
    for (int i = 1; i <= n; i++) {
      scanf("%d", &m);
      sum = 3;
      while (m--) sum = 2 * (sum - 1);
      printf("%d\n", sum);
    }
  }
  return 0;
}

Problem Description
網上流傳一句話:"常在網上飄啊,哪能不挨刀啊~"。其實要想能安安心心地上網其實也不難,學點安全知識就可以。
首先,我們就要設定一個安全的密碼。那什麼樣的密碼才叫安全的呢?一般來說一個比較安全的密碼至少應該滿足下面兩個條件:
(1).密碼長度大於等於8,且不要超過16。
(2).密碼中的字元應該來自下面“字元類別”中四組中的至少三組。
這四個字元類別分別為:
1.大寫字母:A,B,C...Z;
2.小寫字母:a,b,c...z;
3.數字:0,1,2...9;
4.特殊符號:~,!,@,#,$,%,^;
給你一個密碼,你的任務就是判斷它是不是一個安全的密碼。
Input
輸入資料第一行包含一個數M,接下有M行,每行一個密碼(長度最大可能為50),密碼僅包括上面的四類字元。
Output
對於每個測試例項,判斷這個密碼是不是一個安全的密碼,是的話輸出YES,否則輸出NO。
Sample Input
3
a1b2c3d4
Linle@ACM
^~^@^@!%
Sample Output
NO
YES
NO

做這題的時候好像還在JNUCTF期間,滿腦子弱口令,邊做還邊想這給的樣例跑字典跑不出來啊...
咳咳迴歸正題,就是判斷每一個制胡竄是不是都包含四種字元中的三種,具體判斷見程式碼

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

int m;
char a[51];

int main() {
  while (scanf("%d", &m) != EOF) {
    getchar();
    for (int i = 1; i <= m; i++) {
      int num1, num2, num3, num4;
      num1 = num2 = num3 = num4 = 0;
      gets(a);
      int len = strlen(a);
      if (len < 8 || len > 16) {
        printf("NO\n");
        continue;
      }
      for (int i = 0; i < len; i++) {
        if ('a' <= a[i] && 'z' >= a[i]) num1 = 1;
        if ('A' <= a[i] && 'Z' >= a[i]) num2 = 1;
        if ('0' <= a[i] && '9' >= a[i]) num3 = 1;
        if (a[i] == '~' || a[i] == '!' || a[i] == '@' || a[i] == '#' || a[i] == '$' || a[i] == '%' || a[i] == '^') num4 = 1;
      }
      int num = num1 + num2 + num3 + num4;
      if (num >= 3) printf("YES\n");
      else printf("NO\n");
     }
  }
  return 0;
}

Problem Description
有一隻經過訓練的蜜蜂只能爬向右側相鄰的蜂房,不能反向爬行。請程式設計計算蜜蜂從蜂房a爬到蜂房b的可能路線數。
其中,蜂房的結構如下所示。

Input
輸入資料的第一行是一個整數N,表示測試例項的個數,然後是N 行資料,每行包含兩個整數a和b(0<a<b<50)。
Output
對於每個測試例項,請輸出蜜蜂從蜂房a爬到蜂房b的可能路線數,每個例項的輸出佔一行。
Sample Input
2
1 2
3 6
Sample Output
1
3

經典題目了,10月左右安徽大學acm新生賽好像還出了一道這題的變形,這裡整一個高精版的:洛谷P2437蜜蜂路線
同樣也是一個斐波那契數列,第m個蜂房可以通過第m-1和第m-2個蜂房到達,剩下的就和樓梯那題一個樣了

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

long long n, dp[1001];

int main() {
  while (scanf("%lld", &n) != EOF) {
    dp[1] = 1;
    dp[2] = 2;
    for (int i = 1; i <= n; i++) {
      long long a, b;
      scanf("%lld%lld", &a, &b);
      for (int i = 3; i <= b - a; i++) dp[i] = dp[i - 1] + dp[i - 2];
      printf("%lld\n", dp[b - a]);
    }
  }
  return 0;
}
  • HDU2045 不容易系列之(3)—— LELE的RPG難題
    題目連結

Problem Description
人稱“AC女之殺手”的超級偶像LELE最近忽然玩起了深沉,這可急壞了眾多“Cole”(LELE的粉絲,即"可樂"),經過多方打探,某資深Cole終於知道了原因,原來,LELE最近研究起了著名的RPG難題:
有排成一行的n個方格,用紅(Red)、粉(Pink)、綠(Green)三色塗每個格子,每格塗一色,要求任何相鄰的方格不能同色,且首尾兩格也不同色.求全部的滿足要求的塗法.
以上就是著名的RPG難題.
如果你是Cole,我想你一定會想盡辦法幫助LELE解決這個問題的;如果不是,看在眾多漂亮的痛不欲生的Cole女的面子上,你也不會袖手旁觀吧?
Input
輸入資料包含多個測試例項,每個測試例項佔一行,由一個整數N組成,(0<n<=50)。
Output
對於每個測試例項,請輸出全部的滿足要求的塗法,每個例項的輸出佔一行。
Sample Input
1
2
Sample Output
3
6

這題當時想了挺久的,這裡詳細說一下吧
核心程式碼為:f[i] = f[i - 1] + f[i - 2] * 2;
但是為啥子嘞?我們以5個格子的情況舉例
假設五個格子,三個顏色:紅黃藍,第一個格子假設塗紅色
先看第一種情況(5 = 4 + 1):
-先塗好四個格子,則第四個格子和第一個格子顏色一定不一樣,那麼第五個格子有且只有一種取法
-在此情況下的方案數為f[4]
再看第二種情況(5 = 3 + 2):
-先塗好三個格子,再塗後兩個,則此時第四個格子是不會受到第一個格子的顏色的約束的,由於第一種情況已經計算了第四個格子為黃藍的情況,我們這裡只需考慮紅色即可,此時第五個格子便可取黃藍
-所以在這個情況下的方案數為f[3] * 2
總的來說,第五個格子的方案數即為f[4] + f[3] * 2
其餘同理

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

long long n, f[1001];

int main() {
  while (scanf("%lld", &n) != EOF) {
    f[0] = 0;
    f[1] = 3;
    f[2] = 6;
    f[3] = 6; 
    for (int i = 4; i <= n; i++) 
      f[i] = f[i - 1] + f[i - 2] * 2;
    printf("%lld\n", f[n]);
  }
  return 0;
}

Problem Description
在2×n的一個長方形方格中,用一個1× 2的骨牌鋪滿方格,輸入n ,輸出鋪放方案的總數.
例如n=3時,為2× 3方格,骨牌的鋪放方案有三種,如下圖:

Input
輸入資料由多行組成,每行包含一個整數n,表示該測試例項的長方形方格的規格是2×n (0<n<=50)。
Output
對於每個測試例項,請輸出鋪放方案的總數,每個例項的輸出佔一行。
Sample Input
1
3
2
Sample Output
1
3
2

又是遞推...好多遞推題啊...
遞推式還是那個遞推式,可以解釋為在f[n-1]的基礎上豎著加一個長方塊以及在f[n-2]的基礎上橫著放倆長方塊

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

long long n, dp[51];

int main() {
  while (scanf("%lld", &n) != EOF) {
    dp[1] = 1;
    dp[2] = 2;
    for (int i = 3; i <= n; i++) 
      dp[i] = dp[i - 1] + dp[i - 2];
    printf("%lld\n", dp[n]);
  }
  return 0;
}

Problem Description
今年的ACM暑期集訓隊一共有18人,分為6支隊伍。其中有一個叫做EOF的隊伍,由04級的阿牛、XC以及05級的COY組成。在共同的集訓生活中,大家建立了深厚的友誼,阿牛準備做點什麼來紀念這段激情燃燒的歲月,想了一想,阿牛從家裡拿來了一塊上等的牛肉乾,準備在上面刻下一個長度為n的只由"E" "O" "F"三種字元組成的字串(可以只有其中一種或兩種字元,但絕對不能有其他字元),阿牛同時禁止在串中出現O相鄰的情況,他認為,"OO"看起來就像發怒的眼睛,效果不好。
你,NEW ACMer,EOF的崇拜者,能幫阿牛算一下一共有多少種滿足要求的不同的字串嗎?
PS: 阿牛還有一個小祕密,就是準備把這個刻有 EOF的牛肉乾,作為神祕禮物獻給杭電五十週年校慶,可以想象,當校長接過這塊牛肉乾的時候該有多高興!這裡,請允許我代表杭電的ACMer向阿牛表示感謝!
再次感謝!
Input
輸入資料包含多個測試例項,每個測試例項佔一行,由一個整數n組成,(0<n<40)。
Output
對於每個測試例項,請輸出全部的滿足要求的塗法,每個例項的輸出佔一行。
Sample Input
1
2
Sample Output
3
8

和RPG那題大同小異,也是兩種情況
第一種:n-1不是O,方案數就是f[n-1] * 2
第二種:n-1是O,方案數就是f[n-2] * 2
得到遞推式f[n] = f[n-2] * 2 + f[n-1] * 2

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

int n;
long long a[51];

int main() {
  while (scanf("%d", &n) != EOF) {
    a[1] = 3;
    a[2] = 8;
    for (int i = 3; i <= n; i++)
      a[i] = 2 * a[i - 1] + 2 * a[i - 2];
    printf("%lld\n", a[n]);
  }
  return 0;
}

Problem Description
HDU 2006'10 ACM contest的頒獎晚會隆重開始了!
為了活躍氣氛,組織者舉行了一個別開生面、獎品豐厚的抽獎活動,這個活動的具體要求是這樣的:
首先,所有參加晚會的人員都將一張寫有自己名字的字條放入抽獎箱中;
然後,待所有字條加入完畢,每人從箱中取一個字條;
最後,如果取得的字條上寫的就是自己的名字,那麼“恭喜你,中獎了!”
大家可以想象一下當時的氣氛之熱烈,畢竟中獎者的獎品是大家夢寐以求的Twins簽名照呀!不過,正如所有試圖設計的喜劇往往以悲劇結尾,這次抽獎活動最後竟然沒有一個人中獎!
我的神、上帝以及老天爺呀,怎麼會這樣呢?
不過,先不要激動,現在問題來了,你能計算一下發生這種情況的概率嗎?
不會算?難道你也想以悲劇結尾?!
Input
輸入資料的第一行是一個整數C,表示測試例項的個數,然後是C 行資料,每行包含一個整數n(1<n<=20),表示參加抽獎的人數。
Output
對於每個測試例項,請輸出發生這種情況的百分比,每個例項的輸出佔一行, 結果保留兩位小數(四捨五入),具體格式請參照sample output。
Sample Input
1
2
Sample Output
50.00%

高中數學,排列組合
阿巴阿巴阿巴,好像是那個什麼錯排
求概率其實就是分子(錯排)/分母(n!)。分母很好算,我們接下來考慮一下分子
考慮第n個數,假設把它放在了k的位置上,有n-1種方法,那麼對於第k個數字放在哪裡,又可以分兩種情況討論:
1、把第k個數放在n的位置上,那麼就是剩下的n-2個數的錯排問題
2、不把第k個數放在n的位置上,那麼就是剩下n-1個數的錯排問題
所以分子的遞推關係式為:f[n] = (n - 1) * (f[n - 1] + f[n - 2]),注意初始化a[1] = 0; a[2] = 1;

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

int n, m;
double a[21], b[21];

int main() {
  while (scanf("%d", &n) != EOF) {
    for (int i = 1; i <= n; i++) {
      scanf("%d", &m);
      a[1] = 0;
      a[2] = 1;
      b[1] = 1;
      b[2] = 2;
      for (int i = 3; i <= m; i++) {
        a[i] = (i - 1) * (a[i - 1] + a[i - 2]);
  	b[i] = b[i - 1] * i;
      }
      printf("%.2lf%%\n", (a[m] / b[m]) * 100);
    }
  }
  return 0;
}

Problem Description
國慶期間,省城HZ剛剛舉行了一場盛大的集體婚禮,為了使婚禮進行的豐富一些,司儀臨時想出了有一個有意思的節目,叫做"考新郎",具體的操作是這樣的:
首先,給每位新娘打扮得幾乎一模一樣,並蓋上大大的紅蓋頭隨機坐成一排;
然後,讓各位新郎尋找自己的新娘.每人只准找一個,並且不允許多人找一個.
最後,揭開蓋頭,如果找錯了物件就要當眾跪搓衣板...
看來做新郎也不是容易的事情...
假設一共有N對新婚夫婦,其中有M個新郎找錯了新娘,求發生這種情況一共有多少種可能.
Input
輸入資料的第一行是一個整數C,表示測試例項的個數,然後是C行資料,每行包含兩個整數N和M(1<M<=N<=20)。
Output
對於每個測試例項,請輸出一共有多少種發生這種情況的可能,每個例項的輸出佔一行。
Sample Input
2
2 2
3 2
Sample Output
1
3

高中排列組合,從n中選出m個,然後乘上錯排公式,即C[m][n] * f[n](f[n]為n的錯排)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

int c, n, m;
long long f[21];

long long work(int n, int m) {
  long long sum1, sum2;
  sum1 = sum2 = 1;
  for (int i = n; i >= n - m + 1; i--)
    sum1 *= i;
  for (int i = 1; i <= m; i++)
    sum2 *= i;
  return sum1/sum2;
}

int main() {
  while (scanf("%d", &c) != EOF) {
    for (int i = 1; i <= c; i++) {
      scanf("%d%d", &n, &m);
      long long ans;
      f[1] = 0;
      f[2] = 1;
      for (int j = 3; j <= m; j++)
  	f[j] = (j - 1) * (f[j - 1] + f[j - 2]);
      ans = work(n, m) * f[m];
      printf("%lld\n", ans);
    }
  }
  return 0;
}