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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Task 10 统计从1到某个整数之间出现的1的次数

發布時間:2024/4/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Task 10 统计从1到某个整数之间出现的1的次数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ?任務:給定一個十進制的正整數,寫下從1開始,到N的所有整數,然后數一下其中出現“1”的個數。

? ? ?要求: 寫一個函數 f(N) ,返回1 到 N 之間出現的 “1”的個數。例如 f(12) = 5。

? ? ? ? ? ? ? ?在32位整數范圍內,滿足條件的“f(N) =N”的最大的N是多少。

?

1.設計思想:因為上課很多同學都給出了一個一個數地求出所出現的1,最多每個數也就求5、6次,但是所給的整數很大的時候計算機會一下循環遞歸N次來計算1的次數,這樣會導致效率非常低。我們都知道每個位數上都有一定的規律,每一位上出現1的次數都和其前一位和后一位以及當前位上的數字有關系,所以得通過大量的數據一位一位的進行分析,進而找到每個數的規律。

?

通過對1位數、2位數、3位數,,,進行分析統計,發現如果當前位上的數字為0,1,大于等于1時有不同的情況;則此位上出現的1的次數分別會由更高位數上、更低位或者當前位的數字決定,具體如下:

假設一個數為abcde

如果百位上數字c為0,百位上可能出現1的次數由更高位決定。比如:33033,則可以知道百位出現1的情況可能是:100~199,1100~1199,2100~2199,,.........,32100~32199,一共3300個。可以看出是由更高位數字(12)決定,并且等于更高位數字(ab)乘以 當前位數(100)。

如果百位上數字為1,百位上可能出現1的次數不僅受更高位影響還受低位影響。比如:33133,則可以知道百位受高位影響出現的情況是:100~199,1100~1199,2100~2199,,.........,32100~32199,一共3300個。和上面情況一樣,并且等于更高位數字(ab)乘以 當前位數(100)。但同時它還受低位影響,百位出現1的情況是:33100~33133,一共134個,等于低位數字(cde)+1。

如果百位上數字大于1(2~9),則百位上出現1的情況僅由更高位決定,比如12213,則百位出現1的情況是:100~199,1100~1199,2100~2199,...........,11100~11199,12100~12199,一共有1300個,并且等于更高位數字+1(ab+1)乘以當前位數(100)。

除了百位上其他位數也都符合這個規律,所以只需要循環整數的位數次就可以求出最終的結果。

然后第二步實現的時候,開始以為只需要一個循環就行了,讓計算機循環。不過由于基數太大所以會用很長時間

將要計算的范圍劃分為幾個區間,然后對每個區間進行計算。比如說:

1到999,先將這些數劃分為10個區間:1-99、100-199 … 900-999

由f(999) = 300可知,300以后的區間段可以不計算。當計算200時,可以先計算299,由于f(299)=160<200,200-299的區間可以都不必計算。對要計算的區間,再將它劃分為10個區間,重復進行。這樣劃分的另一個好處是利用公式:f(10^n-1) = n * 10^(n-1),保存上次算得的f(n)直接計算下個數的f(n)。

2.源代碼:

#include<iostream> using namespace std;int Count(int n){int count = 0;//1的個數int CurrentPosition = 1;//當前位int LowerNum = 0;//低位數字int CurrNum = 0;//當前位數字int HigherNum = 0;//高位數字while(n / CurrentPosition != 0){LowerNum = n - (n / CurrentPosition) * CurrentPosition;//低位數字 CurrNum = (n / CurrentPosition) % 10;//當前位數字 HigherNum = n / (CurrentPosition * 10);//高位數字if(CurrNum == 0)//如果為0,出現1的次數由高位決定 {count += HigherNum * CurrentPosition;//等于高位數字 * 當前位數 }else if(CurrNum == 1)//如果為1,出現1的次數由高位和低位決定 {count += HigherNum * CurrentPosition + LowerNum + 1;//高位數字 * 當前位數 + 低位數字 + 1 }else//如果大于1,出現1的次數由高位決定 {count += (HigherNum + 1) * CurrentPosition;//(高位數字+1)* 當前位數 }CurrentPosition *= 10;//前移一位 }return count; }void main() {int a;cout << "請輸入一個正整數:";cin >> a;cout << a;cout << "從1到該數字出現的1的次數為:" << Count(a) << endl;for (int i = 0; i < 4294967295 ; i++){if( Count(i) == i){cout << i << " ";}} }

改進之后:

#include<iostream> using namespace std;int Count(int n){int count = 0;//1的個數int CurrentPosition = 1;//當前位int LowerNum = 0;//低位數字int CurrNum = 0;//當前位數字int HigherNum = 0;//高位數字while(n / CurrentPosition != 0){LowerNum = n - (n / CurrentPosition) * CurrentPosition;//低位數字 CurrNum = (n / CurrentPosition) % 10;//當前位數字 HigherNum = n / (CurrentPosition * 10);//高位數字if(CurrNum == 0)//如果為0,出現1的次數由高位決定 {count += HigherNum * CurrentPosition;//等于高位數字 * 當前位數 }else if(CurrNum == 1)//如果為1,出現1的次數由高位和低位決定 {count += HigherNum * CurrentPosition + LowerNum + 1;//高位數字 * 當前位數 + 低位數字 + 1 }else//如果大于1,出現1的次數由高位決定 {count += (HigherNum + 1) * CurrentPosition;//(高位數字+1)* 當前位數 }CurrentPosition *= 10;//前移一位 }return count; }inline unsigned count_digits(unsigned long long num) {unsigned long long n = 1;unsigned ret = 0;while (n <= num) { n *= 10; ++ret; }return ret; }void get_nums() {unsigned long long x = 1e11 - 1, y;unsigned count = 0;unsigned idx = 0;while (true){++count;y = Count(x);if (x < y) {//x在1到10時,均不滿足x<y,所以x>10,下面的k值肯定大于0 unsigned k = count_digits(x) - 1;x -= (y - x - 1)/k + 1; }else if (x > y) { x = y; } else{cout<< ++idx << ": " << x << endl;//break;--x;if (x == 0) break;} } }void main() {int a;cout << "請輸入一個正整數:";cin >> a;cout << a;cout << "從1到該數字出現的1的次數為:" << Count(a) << endl;cout << "整數與次數相同的有以下這些,最大值為第一個數:";get_nums(); }

?

3.實驗截圖:

4.實驗總結:

? ? (1)這個題目跟之前的同樣是數學題類型的程序,需要利用大量的來分析統計,從中得出規律,否則就失去了編程的高效性;

? ? (2)而當完成第一步之后以為第二步很簡單,其實不然。感覺當時一定是被成功的喜悅蒙蔽了雙眼,只是看它一直在滾動數字,而且也得出了最后的結果,然而卻沒想到效率的問題,之才發現第二步的設計也包含了好多規律,所以一定要從頭到尾保持清醒的頭腦。

轉載于:https://www.cnblogs.com/mengxiangjialzh/p/4548613.html

總結

以上是生活随笔為你收集整理的Task 10 统计从1到某个整数之间出现的1的次数的全部內容,希望文章能夠幫你解決所遇到的問題。

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