《ACM国际大学生程序设计竞赛题解Ⅰ》——模拟题
??這篇文章來介紹一些模擬題,即一類按照題目要求將現實的操作轉換成程序語言。
?
??zoj1003:
? On every June 1st, the Children's Day, there will be a game named "crashing balloon" on TV. ? The rule is very simple.? On the ground there are 100 labeled? balloons, with the numbers 1 to 100.? After the referee shouts "Let's go!" the two players, who each starts with a score of? "1", race to crash the balloons by their feet and, at the same time, multiply their scores by the numbers written on the balloons they crash.? After a minute, the little audiences are allowed to take the remaining balloons away,? and each contestant reports his\her score, the product of the numbers on the balloons he\she's crashed.? The unofficial winner is the player who announced the highest score.
Inevitably, though, disputes arise, and so the official winner is not determined until the disputes are resolved.? The player who claims the lower score is entitled to challenge his\her opponent's score.? The player with the lower score is presumed to have told the truth, because if he\she were to lie about his\her score, he\she would surely come up with a bigger better lie.? The challenge is upheld if the player with the higher score has a score that cannot be achieved with balloons not crashed by the challenging player.? So, if the challenge is successful, the player claiming the lower score wins.
So, for example, if one player claims 343 points and the other claims 49, then clearly the first player is lying; the only way to score 343 is by crashing balloons labeled 7 and 49, and the only way to score 49 is by crashing a balloon labeled 49.? Since each of two scores requires crashing the balloon labeled 49, the one claiming 343 points is presumed to be lying.
On the other hand, if one player claims 162 points and the other claims 81, it is possible for both to be telling the truth (e.g. one crashes balloons 2, 3 and 27, while the other crashes balloon 81), so the challenge would not be upheld.
By the way, if the challenger made a mistake on calculating his/her score,? then the challenge would not be upheld.? For example, if one player claims? 10001 points and the other claims 10003, then clearly none of them are telling the truth.? In this case, the challenge would not be upheld.
Unfortunately, anyone who is willing to referee a game of crashing balloon is likely to get over-excited in the hot atmosphere that? he\she could not reasonably be expected to perform the intricate calculations that refereeing requires.? Hence the need for you, sober programmer, to provide a software solution.
Input
Pairs of unequal, positive numbers, with each pair on a single line, that are claimed scores from a game of crashing balloon.
Output
Numbers, one to a line, that are the winning scores, assuming that the player with the lower score always challenges the outcome.
?
??題目大意:給出兩個整數n、m(假設m>n),請你判斷是否存在一種方案,使得n = f1 * f2?*...?,?m=F1 * F2 *...,其中對于任意的i、j,有fi≠fj,fi≠Fj,fi∈[2,100]且fj∈[2,100]。
??數理分析:其實對于題目大意的描述,筆者表述很抽象化,如果用文字描述,其實就是判斷對于給出的兩個整數n、m,進行因數分解(因子范圍在1~100),能否得到兩個完全不同的方案。假設我們已經得到了結果,我們先看看這個結果如何左右我們輸出的結果。
??如果存在這樣一種方案,結合原文題意,這里駁回質疑,高分勝出,即輸出m、n當中較高的那個。
??如果不存在這樣一種方案,則質疑成功,低分勝出,輸出m、n中較小的那個。
??這里注意到原文的一段話,“By the way, if the challenger made a mistake on calculating his/her score,? then the challenge would not be upheld.? For example, if one player claims? 10001 points and the other claims 10003, then clearly none of them are telling the truth.? In this case, the challenge would not be upheld.”這句話是說,如果m、n兩者都沒辦法完成上述的因數分解,即用原文的話說是兩個人都說謊,則不支持提出的質疑,按照原來的勝負態來處理,也就是高分或者獲勝。
??總結起來,如果想輸出較小的數,當且僅當m、n在所以的因數分解中,n能夠被因數分解但是m不能。而其余的情況都是輸出較大數m。
??搞清的如何輸出,下面我們要解決的關鍵問題就是如何判斷筆者在題目大意中描述的那個數學問題呢?
??其實筆者感覺這道題放在模擬題中有點“干”,它其實涉及了數論的東西和dfs的思想(關于搜索后面會有一篇文章專門介紹)。
??判斷方法描述起來很簡單,我們找到m、n所有的因數分解情況,然后按照給出的限制條件去判斷即可。
??但是如何巧妙的變成來實現這個過程呢?要先對m、n質因分解然后排列組合么?理論上可行但似乎有些繁瑣。考慮到每個因子僅能出現一次的特點,我們利用dfs進行深搜,我們首先從枚舉100開始枚舉2~100這99個因子,一旦發現一個m或者n的因子pm或pn(假設當前找到了m的一個因子pm),那么我們可以將問題更加的微小化。即一開始,我們當前的問題是判斷整數m、n是否能夠得到兩種不同的因數分解方案,因子范圍是2~100,那么在找到了某個因子pm之后,我們的問題便可以縮小化成如下的等價形式,判斷m/pm、n是否能夠得到兩種不同的因數分解方案,因子范圍是2~pm-1,由此我們看到這遞歸的程序模式,其實如果熟悉歐幾里得算法的讀者,會更好的理解這個過程。
??簡單的參考代碼如下。
?
#include<cstdio> using namespace std; bool atrue , btrue;int judge(int m,int n,int p) {if(atrue) return 0;if(n == 1 && m == 1){atrue = true;btrue = true;return 0;}if(n == 1) btrue = true;while(p > 1){if(m%p == 0) judge(m/p,n,p-1);if(n%p == 0) judge(m,n/p,p-1);p--;}return 0; } int main() {int a , b , temp;while(scanf("%d%d",&a,&b) != EOF){if(b > a){temp = a;a = b;b = temp;}atrue = false;btrue = false;judge(a , b , 100);if(!atrue && btrue)printf("%d\n",b);elseprintf("%d\n",a);} }?
轉載于:https://www.cnblogs.com/rhythmic/p/5555308.html
總結
以上是生活随笔為你收集整理的《ACM国际大学生程序设计竞赛题解Ⅰ》——模拟题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原创:1991年,日本“失去的十年”,那
- 下一篇: 原创:诸葛亮的妻子真的很丑吗?关于这个问