51nod 1536不一样的猜数游戏 思路:O(n)素数筛选法。同Codeforces 576A Vasya and Petya‘s Game。
廢話不多說,先上題目。
?
51nod
?
?
Codeforces
?
?
?
兩個其實是一個意思,看51nod題目就講的很清楚了,題意不再贅述。
直接講我的分析過程:剛開始拿到手有點蒙蔽,看起來很難,然后。。。。。。然后我就開始一頓胡蒙,各種舉例子、找規律下面為我取n = 10的過程。
?
?
?
1.首先1肯定不用取。因為它太特殊了,如果 取它的話,只能判斷是不是1,因為所有數都是1的倍數;反之其他所有情況排除了就選它,不用浪費次數來取它。
?
2.素數肯定是要取的。因為。。。。。。因為這題一看就是考素數的題。
?
3.以10為例,如果是2,3的倍數,則為6。如果是2,5的倍數則為10。如果不是2的倍數,是5的倍數則為。如果是7的倍數則為7。現在我們根據2,3,5,7這4個素數選出了6,10,5,7這4個數。肯定還要再加數,怎么加?
?
4.如果加一個數能多判斷更多的數最好了,先考慮3,3的倍數有3、6和9,6我們用2、3組合判斷過了,3和9能怎么判斷?肯定不能不選3而選9用排除法,因為1已經用了排除法,排除法只能用一次。因為要判斷所有數字,想要判斷3和9必須要同時取3和9,這樣只多取了一個9我們就多判斷了兩個數字。現在我們能判斷6、10、5、7、3、9這6個數字了。
?
5.再看2,2的倍數有2、4、6、8、10。6和10我們已經用2、3和2、5組合判斷了,我們觀察剩余的數字還有2、4、8,我尼瑪?什么情況,如果剛剛的3和9是巧合的話,這里的2、4、8還是巧合?現在我們取中2、4、8三個數就可以判斷這3個數了。我們判斷出了9個數6、10、5、7、3、9、2、4、8,然后1用排除法,所以我們判斷出了這10個數了。
?
?
?
這里我們觀察到我們選出的都是素數的次方(小于n)。以10為例,2,4,8(2的次方);3,9(3的次方);5(5的次方);7(7的次方)。然后多試幾例,發現就是這個規律。
?
?
現在我們有兩條路可走:
?
?
?
然后分析,發現第一條路只用找出素數及其次方,第二條路要在第一條路的基礎上做更多工作,所以果斷選擇第一條路。
?
?
?
下面是代碼了:
再加點注釋:
#include <bits\stdc++.h> using namespace std;//素數篩選法 O(n) ,見那本小紅書(ACM國際大學生程序設計競賽-算法與實現) int ans[1001]; //存入所有素數。 bool valid[1001]; //判斷第i個是不是素數。 void getPrime(int n,int &tot){memset(valid,true,sizeof(valid));for(int i = 2;i <= n; i++){if(valid[i]){tot++;ans[tot] = i;}for(int j = 1;((j <= tot)&&(i*ans[j] <= n)); j++){valid[i*ans[j]] = false;if(i%ans[j] == 0) break;}} }int main(){int n;cin >> n;int res = 0; // 素數及其次方的數量 int tot = 0; // 小于等于n的素數的數量 getPrime(n,tot); //篩選出素數 for(int i = 1;i <= tot; i++){ //遍歷范圍內素數,找出其次方 int t = ans[i];while(t <= n){res++;t*= ans[i];}}cout << res << endl;return 0; }?
?
總結
以上是生活随笔為你收集整理的51nod 1536不一样的猜数游戏 思路:O(n)素数筛选法。同Codeforces 576A Vasya and Petya‘s Game。的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Codeforces 793b B. I
- 下一篇: Android Studio安装应用时报