日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

计算4000000000内的最大f(n)=n值---字符串的问题python实现(五岁以下儿童)

發布時間:2023/12/29 python 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 计算4000000000内的最大f(n)=n值---字符串的问题python实现(五岁以下儿童) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題:

? ? ? ?寫一個函數,計算4 000 000 000 以內的最大的那個f(n)=n的值,函數f的功能是統計全部0到n之間全部含有數字1的數字和。比方:f(13)= 6,由于“1”在“1,2,3,4,5,6,7,8,9,10,11,12,13”中的總數是6(1,10,11,12,13)。

分析:

? ? ? ?一、簡單算法 — 枚舉

? ? ? ?採用“枚舉法”對每一個數都計算一遍1的個數。直到枚舉完給定范圍全部數,找到符合f(n)=n的數。此方法,代碼效率極低。運算所需時間巨大。

python版本號代碼例如以下:

# -*- coding:utf-8 -*- # 問題:寫一個函數。計算4 000 000 000 以內的最大的那個f(n)=n的值, # 函數f的功能是統計全部0到n之間全部含有數字1的數字和。比方:f(13)= 6, # 由于“1”在“1,2,3,4,5,6,7,8,9,10,11,12,13”中的總數是6(1,10,11,12,13)。 # by chasdmeng import time def Calculation_One_Times(n):res = 0while n > 0:if n == 1:res +=1n /=10return resif __name__ == '__main__':times = 0i = 0gMAX = 4000000000Lstart = time.time()while i < gMAX:times +=Calculation_One_Times(i)if times ==i:print "f(", i, ") = ", timesi +=1end = time.time()print "time:",end - start

? ? ? ? 二、高效算法 — 剪枝

? ? ? ?主要採用剪枝算法對代碼運行效率進行優化。求解MAX(f(n)=n)詳細算法構建分析例如以下:

? ? ? ?1、求數字“0~n”中“1”的個數

? ? ? ?基本思想:

? ? ? ?t位數字n,求0到n全部數字“1”的數字和。可對1到t位(1相應個位)。每一個位置上“1”出現的次數分別統計,然后求和。

? ? ? ?如果。0到n之間的自然數范圍內。統計第m位為“1”的個數和。能夠分四步驟。第一步驟,如果第二、三步驟的前提條件為第1到第m-1位內各位數字取固定值a。第二步驟。求大于m位的數字中有多少個數字第m位為“1”。

第三步驟,求等于m位的數字中有多少個數字第m位為“1”。

第四步驟,把第1到第m-1位內各位數字變化考慮進去。例如以下圖所看到的。


? ? ? ?在第二步驟中,須要分兩種情況考慮:

? ? ? (a)給定數n的第m位非0

? ? ? ?大于m位的數字中第m位為“1”的數字個數是n/10^m。

????????(b)給定數n的第m位為0
????? ?對于m位的數字中第m位為“1”的數字個數為(n/10^m)-1。這里舉例說明,n=300。m=2。由于300的第2位為0。此時n/10^m=3。若按(a)中方法求解得出在第1位固定取a 的條件下(第一步驟中規定的)大于2位的數字中第2位為“1”的數字個數是3,這顯然是錯誤的,由于在0到300中這種數僅僅有“11a”、“21a”,此時正確個數應該是n/10^m-1=2。
????? (c)合并考慮

???????大于m位的數字中第m位為“1”的數字個數為(n/(10^(m-1))-1)/10。構造了一個通用公式能夠包括(a)、(b)兩種情況。

原理是。n/10^m=(n/(10^(m-1)))/10,因為是對n做除是向下取整運算,在給定數n第m位非0情況下。n/10^m=(n/(10^(m-1)))/10=(n/(10^(m-1))-1)/10;而當給定數n第m位為0情況下,(n/10^m)-1=(n/(10^(m-1))-1)/10。能夠舉詳細數字對其驗證。
???????在第三步驟中,因為在第一步驟假定的前提條件。滿足求等于m位的數字中第m位為“1”的個數僅僅有1個。

這里舉例說明,n=300。m=2。2位數字中第2位為“1”的數僅有“1a”。
? ? ? ?在第四步驟中,綜合第一、二、三步驟后。在第1到第m-1位內各位數字取固定值a的條件下,第m位為“1”的個數和為(n/(10^(m-1))- 1)/10+1。

以下把第1到第m-1位內各位數字變化考慮進去,因為在第1到第m-1位中每一位能夠放0~9之間隨意數。m-1位數共同擁有“10^m-1”個。

終于,0到n之間的自然數范圍內,第m位為“1”的個數和((n/(10^(m-1))- 1)/10+1)*(10^(m-1))。
? ? ? ?小結:對以上分析結果給予公式化定義。Cm=((n/i - 1)/10 + 1)*i,當中i=10^(m-1),n為隨意自然數。Cm為0到n的數中第m位為1 的 個數和。

? ? ? ?求數字“0~n”中“1”個數的GetTimes()函數,python版代碼例如以下

def GetTimes(n):temp = ntemp2 =1ret = 0i = 1while temp/i:ret +=(((temp/i-1)/10)+1)*iif(((temp/i)%10) == 1):ret -=iret +=temp2i*=10temp2=n%i+1return ret

? ? ? ?2、從0到n位最大數之間1的總個數,尋找數學規律

? ? ? ?當n=1,2,3,...,6,...時。分別計算從0到n位最大數之間1的總個數,部分數據例如以下:

? ? ? ?0~9 ? ? ? ? ?:1
? ? ? ?0~99 ? ? ? ?:20 = 10*1 + 10
? ? ? ?0~999 ? ? ?:300 = 10*20 + 100
? ? ? ?0~9999 ? ?:4000 = 10*300 + 1000
? ? ? ?0~99999 ?:50000 = 10*4000 + 10000
? ? ? ?0~999999:600000 = 10*50000 + 100000
? ? ? ?… ? ? ? ? ? ? ? ? ??

? ? ? ?從中。能夠發現例如以下規律:

? ? ? ?a1 = 1
? ? ? ?a2 = 10*a1 + 10
? ? ? ?…
? ? ? ?an = 10*an - 1 + 10^(n - 1)
? ? ? ?即0~9…9(n個9)之間1的個數為an=10*an-1+10^(n-1)個。

? ? ? ?這樣,當計算隨意一個數字n的0到n之間全部數字1的個數和時,能夠採用將數字n拆分成0~9、0~99... 等部分進行之間計算。

比如:n=123。可將n拆分為0~99和100~123計算:(1)0~99相應1的個數和直接可知為20;(2)百位數1的個數為23+1個。(3)剩下的0~23繼續拆分為0~9、10~19、20~23,共兩個0~9個數為2;(4)由于23中十位數2>1,十位為1的個數10;(5)如今就剩下20~23了,個數為1。所以,0~123中1的個數為20+24+2+10+1=57。

? ? ? ?因此,在求隨意數0~n內全部1的個數和時,能夠首先建立“int ?gTable[10]”結構用于存放a1、a2、a3、...、a9、a10。當中an表示0~n內全部1的個數,然后將數n拆分為0~9、0~99... 等部分直接使用gTable的值進行計算。

這樣的方式能夠提高算法效率。

? ? ? ?生成gTable[]結構的TimesTable()函數。python版代碼例如以下:

def TimesTable(n):return [GetTimes(10**(i+1) - 1) for i in xrange(n)]

? ? ? ?3、採用剪枝算法搜索0~n之間滿足f(q)=q的數

? ? ? ?因為若對0~n的全部數據進行枚舉驗證f(q)=q,當n值非常大時運算相當費時,從本文開頭給出的“最簡單方法”中能夠感受到代碼效率有多么低。為了優化算法提高效率可採用減枝算法,其思想是對0~n之間全部數建立搜索樹,對不符合條件的搜索樹進行剪枝,這樣就能夠極大縮小搜索范圍,提高算法效率。

怎樣構建剪枝規則呢?首先對這個問題進行數學化描寫敘述:

? ? ? ?定義1:設 f(x)=y,當中x∈ (0,n),f為x與相應的(0,x)上全部數字1的個數總和y的映射。

? ? ? ?先觀察下f(n)的特點,能夠發現f(n)是一個單調遞增函數,這樣能夠歸納出它的特性:

? ? ? ?性質1:若有f(m)=a。f(t)=b,且m<t,則存在q∈(m。t)滿足f(q)=q成立的條件是:b>m 且a< t。

? ? ? ?如今就能夠應用“性質1”進行減枝操作。詳細來說通過“性質1”可知,當對0~n的全部數據進行枚舉驗證f(q)=q時,若當f(t)=b<m或f(m)=a>n,則在[m。t]范圍內不存在滿足f(q)=q成立的數q,這樣就可忽略掉[m,t]內這些自然數,直接跳到n+1往后繼續枚舉。在應用剪枝算法枚舉符合條件的f(q)=q時。是以t-m為步長在0~n內逐段排查是否可剪枝,若t-m范圍內不滿足剪枝條件則進行枚舉搜索。因此在進行剪枝算法時[m,t]的范圍取多大適合呢?這是須要謹慎考慮的問題,合理的[m,t]取值能讓大幅提升算法運行效率。

以下就對[m,t]步長L取值進行分析。

? ? ? ?[m,t]的取值根據是能最大化提升算法效率,因為在“2、從0到n位最大數之間1的總個數。尋找數學規律。”中設置了“int ?gTable[10]”結構用于計算f(n),gTable分別表示0~9中1個數和1、0~99中1個數和20、0~999中1的個數和300...。可見是以10^p倍增長,并且f(n)還須要使用gTable去求解,因此初步考慮將[m,t]步長L=10^p。盡管[m,t]取10的倍數,但p詳細取多少,還須要繼續分析。

? ? ? ? 對于隨意s位數m。設s位數的最大值為max(s),則f(max(s))=gTable[s-1],假定取[m,t]步長L=10^s也就是 t=m+10^s,設f(m)=a、f(m+10^s)=b。則有m<max(s)<m+10^s,由于f()為單調增函數,推出gT[s-1]=f(max(s))<f(m+10^s)=b。a<gTable[s-1]。又由于在0~10^10-1的范圍內有max(s)>gTable[s-1](能夠舉例驗證),推出a<gTable[s-1]<max(s)<10+10^s。即a<m+10^s。f(m+10^s)=f(10^s-1)+m+1+f(m)=b。即b>m,因此依據性質1可知m=d*10^s時,取[m。t]步長L=10^s恒不滿足減枝條件。同理步長L=10^(s+1)也無法滿足剪枝條件,因此僅僅能往下取值。對于隨意s位數m,取步長L<=10^(s-1)某些數內能夠滿足減枝條件。舉例來說,m=20,s=2,L=10^(s-1)=10。則在[20。30]內f(20)=12、f(30)=13。依據性質1能夠剪枝掉[20。30]范圍內的數。綜上所述,對隨意s位數m,m∈ (0,n),剪枝算法初始步長L=10^(s-1)? ?。

? ? ? ?性質2:若有f(m)=a,f(t)=b,且m<t,滿足b>m 且a< t時,有f(q)=q,且q∈(m。b]。

? ? ? ?性質2是由性質1推到而來。性質2中將原來性質1中q∈(m,t)縮小為q∈(m。b)。首先在0~10^10-1的范圍內滿足性質1條件下可知b∈(m。t],設f(b+1)=c。則在(b+1,t)內f(b+1)=c、f(t)=b依據性質1不存在q∈(b+1,t)使f(q)=q成立。

所以,在(m,t)內使f(q)=q成立的q∈(m,b]。

? ? ? ? 剪枝算法總體思想是:n位數m,步長L=10^(n-1)。在區間(m-1。m+L-1推斷是否滿足f(m-1)>boundary或f(m+L-1)<m 。滿足就直接跳到m=m+L計算,否則在區間(m-1,f(m+L-1)+L-1)上置步長L=L/10遞歸反復運行剪枝推斷,當遞歸到步長L=1時,進行逐值枚舉f(number)是否等于number。因為算法中m是從0開始枚舉取值,以10的倍數遞增。因此全部的m都應滿足abc*10^s格式,也就是說,m取到的是10的倍數。因此有例如以下性質。

? ? ? ?性質3:m=abc*10^(n-1)。L=10^(n-1)。可知f(m-1+L)=f(m-1)+gTable[n-2]+count_one_m*L。當中count_one_m=f(m)-f(m-1),也就是代表數字m本身包括1的個數。

? ? ? ?剪枝算法CalculationTimes()函數。python版代碼例如以下 :?

def CalculationTimes(number, weight, count_one, count, table):if weight == 0:count += count_oneif number == count:print "f(", number, ") = ", numberreturn countL=10**weightmaxcount = count + table[weight - 1]maxcount += count_one*Lif count > (number + L -1):return maxcountif maxcount < number:return maxcountL /= 10for i in range(10):if i == 1:count = CalculationTimes(number + i*L, weight - 1, count_one + 1, count, table)elif i == maxcount/n - 9:return maxcountelse:count = CalculationTimes(number + i*L, weight - 1, count_one , count, table)return count

? ? ? ?當中。相應前面剪枝算法思想。這里number代表m。weight代表步長L=10^(s-1)?中的s-1,count_one表示數n中各個位置上1的個數,比方n=112,這count_one=2,table代表gTable[]。count代表f(m-1)。詳細解釋例如以下:

if weight == 0:count += count_oneif number == count:print "f(", number, ") = ", numberreturn count此部分代碼推斷當前步長L若為1(L=10^weight)計算f(number)。f(number)通過count+=count_one實現。這是因為在步長L=1前提下,f(number)等于f(number-1)加上數字mumber本身1的個數count_one,既f(number)=f(number-1)+count_one,若f(number)=number。則輸出。否則返回當f(number)。

L=10**weightmaxcount = count + table[weight - 1]maxcount += count_one*Lif count > (number + L -1):return maxcountif maxcount < number:return maxcount

此部分代碼功能運行剪枝操作。首先設置步長L=10^weight。依據性質3得f(number+L-1)=count+table[weight-1]+count_one*L。然后依據性質1推斷能否夠剪枝,若符合條件直接忽略(number-1。number+L-1)范圍內數字并跳轉到number+L再計算。

L /= 10for i in range(10):if i == 1:count = CalculationTimes(number + i*L, weight - 1, count_one + 1, count, table)elif i == maxcount/n - 9:return maxcountelse:count = CalculationTimes(number + i*L, weight - 1, count_one , count, table)return count若不滿足剪枝條件運行此部分代碼。首先依據前面描寫敘述的剪枝算法總體思想將步長縮短L=L/10,然后依據性質2僅需遞歸計算(number-1,f(number+L-1)范圍內數就可以。當i==1時,number+i*L這個數本身將多出一個”1“須要將count_one值加1,當i==maxcount/n-9時,number+i*L將超出范圍終止計算。

? ? ? ?最后,給出總體實現代碼。

# -*- coding:utf-8 -*- # 問題:寫一個函數。計算4 000 000 000 以內的最大的那個f(n)=n的值, # 函數f的功能是統計全部0到n之間全部含有數字1的數字和。

比方:f(13)= 6, # 由于“1”在“1,2,3,4,5,6,7,8,9,10,11,12,13”中的總數是6(1,10,11,12,13)。

# by chasdmeng import time def GetTimes(n): temp = n temp2 =1 ret = 0 i = 1 while temp/i: ret +=(((temp/i-1)/10)+1)*i if(((temp/i)%10) == 1): ret -=i ret +=temp2 i*=10 temp2=n%i+1 return ret def TimesTable(n): return [GetTimes(10**(i+1) - 1) for i in xrange(n)] def CountOne(n): count = 0 while n: if (n%10) == 1:count +=1 n /=10 return count def CalculationTimes(number, weight, count_one, count, table): if weight == 0: count += count_one if number == count: print "f(", number, ") = ", number return count L=10**weight maxcount = count + table[weight - 1] maxcount += count_one*L if count > (number + L -1): return maxcount if maxcount < number: return maxcount L /= 10 for i in range(10): if i == 1: count = CalculationTimes(number + i*L, weight - 1, count_one + 1, count, table) elif i == maxcount/n - 9: return maxcount else: count = CalculationTimes(number + i*L, weight - 1, count_one , count, table) return count if __name__ == '__main__': n = 0 weight = 0 count = 0 count_one = 0 gMAX = 4000000000L start = time.time() table = TimesTable(10) while n < gMAX: count = CalculationTimes(n, weight, count_one , count, table) L = 10**weight n += L if (n/L)/10 == 1: weight +=1 count_one = CountOne(n) end = time.time() print "time:",end - start

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?by ? ? ? chasdmeng

參考文獻:

? ? ? 博客:http://blog.csdn.net/livelylittlefish/article/details/2768348

? ? ? 書籍:《程序猿面試寶典(第4版)》P240。面試例題5





版權聲明:本文博客原創文章。博客,未經同意,不得轉載。

轉載于:https://www.cnblogs.com/zfyouxi/p/4652295.html

總結

以上是生活随笔為你收集整理的计算4000000000内的最大f(n)=n值---字符串的问题python实现(五岁以下儿童)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。