[算法] 两个质数的乘积是707829217,求解该质数
記錄一次有趣的算法題。
土生土長的北京妞兒,在胡同里長大,房不多,就一個四合院和近郊的別墅。不算美如天仙但還算標(biāo)致,在清華讀的經(jīng)管,現(xiàn)在在做基金經(jīng)理(不想被人肉,就不暴露單位啦) ,個人擅長基本面分析,價值投資。現(xiàn)在只想找個聰明靠譜的IT男。硬性要求是年齡,不要超過88年,還有不要特別矮或胖。我對智商的要求比較高,下面就出個題測試下。
我的微信ID是大寫字母NY后面跟著兩個質(zhì)數(shù),大的在前,小的在后,乘積是707829217,可直接搜索添加,另外還有個附加題目,在剛剛微信ID的數(shù)字中,從1開始到這個數(shù)字的奇數(shù)序列里,一共出現(xiàn)了多少個3,如果私信我正確的答案,我將直接邀你見面!期待緣分降臨~
問題1 求解微信號
// 兩個質(zhì)數(shù)的乘積是707829217,求質(zhì)數(shù)int num = 707829217;int i = 1;while (i <= num) {i += 2;if (num % i == 0) {System.out.println("發(fā)現(xiàn): " + num + " / " + i + " = " + (num / i));}}打印結(jié)果:
發(fā)現(xiàn): 707829217 / 8171 = 86627 發(fā)現(xiàn): 707829217 / 86627 = 8171 發(fā)現(xiàn): 707829217 / 707829217 = 1Process finished with exit code 0所以我們得到第一問的答案:NY866278171
問題2 求解奇數(shù)序列中,3出現(xiàn)的次數(shù)
我們看到這個數(shù)值866278171,為8億多,去掉偶數(shù),只看奇數(shù),也有4億多。
問這4億個數(shù)中3出現(xiàn)了多少次,這個問題有點費解。
方式一 暴力破解
所謂暴力破解,就是遍歷每一個數(shù)值,統(tǒng)計3出現(xiàn)的次數(shù)。下面的各個版本僅供參考:
該方案耗時:2m 52s 139ms
// 奇數(shù)序列中,一共出現(xiàn)了多少次3int number = 866278171;int sum = 0;for (int i = 1; i <= number; i = i + 2) {sum += String.valueOf(i).replace("3", "_#_").split("#").length - 1;}// 總數(shù): 441684627System.out.println("總數(shù): " + sum);該方案耗時:1m 41s 259ms
// 奇數(shù)序列中,一共出現(xiàn)了多少次3int number = 866278171;int sum = 0;for (int i = 1; i <= number; i = i + 2) {String str = String.valueOf(i);if (str.contains("3")) {sum += str.length() - str.replace("3", "").length();}}// 總數(shù): 441684627System.out.println("總數(shù): " + sum);該方案耗時:22s 942ms
// 奇數(shù)序列中,一共出現(xiàn)了多少次3int number = 866278171;int sum = 0;for (int i = 1; i <= number; i = i + 2) {String str = String.valueOf(i);for (int j = 0; j < str.length(); j++) {if (str.charAt(j) == '3') {sum++;}}}// 總數(shù): 441684627System.out.println("總數(shù): " + sum);該方案耗時:6s 669ms
// 奇數(shù)序列中,一共出現(xiàn)了多少次3int number = 866278171;int sum = 0;for (int i = 1; i <= number; i = i + 2) {int k = i;while (k > 1) {if (k % 10 == 3) {sum++;}k /= 10;}}// 總數(shù): 441684627System.out.println("總數(shù): " + sum);我們看到,走了好多的彎路,String類中的replace和contains都是重量級方法。當(dāng)我們使用有限次數(shù)時,并不會感覺到慢。但是當(dāng)我們需要重復(fù)執(zhí)行上億次時,就很慢了。
方式二 公式法
規(guī)律總結(jié)
- 對于1位數(shù)
- 對于2位數(shù):
- 對于3位數(shù):
- 對于4位數(shù):
好像有點規(guī)律了。。
對于任意N位數(shù),3出現(xiàn)的次數(shù)為 n * 10^(n-1)
翻譯成代碼:
/*** 任意N位數(shù),3出現(xiàn)的次數(shù)*/public double anyN(int n) {if (n < 1)return 0;return n * Math.pow(10, n - 1);}問題來了,對于一個有限度的N位數(shù),3出現(xiàn)了多少次?
比如: 0 ~ 2918,3出現(xiàn)了多少次?拆分下: 0 ~ 2000區(qū)間段, 可以理解為2個1000,也就是2個任意3位數(shù),所以 :2 * 300 + 0 (對于任意3位數(shù)3出現(xiàn)的次數(shù)為300,不包含3000~3999 整個以3開頭的千位數(shù)) 2000 ~ 2900區(qū)間段, 可以理解為9個100,也就是9個任意2位數(shù),所以:9 * 20 + 100( 任意2位數(shù)3出現(xiàn)的次數(shù)為20,包含300-399 整個以3開頭的百位數(shù)) 2900 ~ 2910區(qū)間段, 可以理解為1個10,也就是1個任意1位數(shù),所以:1 * 1 + 0( 任意1位數(shù)3出現(xiàn)的次數(shù)為1,不包含30-39 整個以3開頭的十位數(shù)) 2910 ~ 2918區(qū)間段, 只看個位數(shù),0 ~ 8,包含一個3,所以: 1 綜合起來就是: (2 * 300 + 0)+(9 * 20 + 100) + (1 * 1 + 0) + (1)= 600+280+1+1 = 882我們拆開翻譯,
- 步驟1
對于0 ~ n * 10^w 的數(shù),3出現(xiàn)了多少次。
比如0~100,0~4000,0~800000000
- 步驟2
對于任意0 ~ N, 3出現(xiàn)了多少次
/*** 計算0~N的數(shù)中,3出現(xiàn)的次數(shù)*/public int anyNumCount3(int anyN) {double sum = 0;int number = anyN;int count0 = 0;while (number > 1) {int n = number % 10;sum += count3(n, count0);if (n == 3) {// 如果該位為3,需要將低位數(shù)再加一遍。// 比如 389,[300,389]共89+1=90個sum += (anyN % Math.pow(10, count0)) + 1;}number /= 10;count0++;}return (int) sum;}該方案耗時:1ms ?
至此,我們通過找規(guī)律,發(fā)現(xiàn)了對于[0~N]中3出現(xiàn)的次數(shù)的公式。
只看奇數(shù)序列
針對本題的只看奇數(shù)序列,我們總結(jié)下規(guī)律:
奇數(shù),也就是限定了個位數(shù)只能是1、3、5、7、9共5種選擇,而更高位可以是0-9共十種選擇。
對于任意N位奇數(shù)
- 對于1位數(shù)
- 對于2位數(shù):
- 對于3位數(shù):
- 對于4位數(shù):
規(guī)律:對于任意N位數(shù),只看奇數(shù),3出現(xiàn)的次數(shù)為1*10^(n-1) + (n-1)*5*10^(n-2)
翻譯成代碼:
/*** 任意N位奇數(shù),3出現(xiàn)的次數(shù)* e.g: 9999 n = 4*/public int anySingleN(int n) {// 1*10^3 + 3*5*10^2if (n < 1) return 0;double sum = Math.pow(10, n - 1);if (n >= 2) {sum += (n - 1) * 5 * Math.pow(10, n - 2);}return (int) sum;}對于有限制的N位奇數(shù),3出現(xiàn)的次數(shù)
- 比如:4000以內(nèi)的奇數(shù)
4個任意三位奇數(shù) + 3開頭的,任意4位奇數(shù)。即4*anySingleN(3) + 10*10*5
翻譯成代碼:
/*** 計算一個 [ 0 , n*10^w ) 的奇數(shù)中,3出現(xiàn)的次數(shù)* <p>* e.g: 4000 n = 4 , w = 3** @param n 數(shù)值* @param w 0的個數(shù)* @return*/public int countSingle3(int n, int w) {// 4 * anySingleN(3) + 5*10^2if (w < 1)// 個位數(shù)return (n >= 3) ? 1 : 0;double sum = n * anySingleN(w);if (n > 3) {sum += 5 * Math.pow(10, w - 1);}return (int) sum;}- 對于0~N的任意奇數(shù)中,3出現(xiàn)的次數(shù)
該方案耗時:1ms ?
至此,我們通過找規(guī)律,發(fā)現(xiàn)了對于[0,N]奇數(shù)序列中3出現(xiàn)的次數(shù)的公式。
總結(jié)
我們通過 方案一 暴力破解 和 方案二 公式法 來解決了這個問題。
速度對比那就更不用說了
總結(jié)
以上是生活随笔為你收集整理的[算法] 两个质数的乘积是707829217,求解该质数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ECE220生存指南[02] MP7:
- 下一篇: Excel里面方框打勾