位數問題
問題描述
在所有的N位數中,有多少個數中有偶數個數字3?由於結果可能很大,你只需要輸出這個答案對12345取余的值。
INPUT
輸入一個數N(1<=N<=1000),輸入以0結束。
OUTPUT
對於每一個N輸出有多少個數中有偶數個數字3。
Sample Input
2
0
Sample Output
73
分析
已知N的最大值為1000,1000位的數字的個數約有101000個,這是個天文數字,故不可能使用枚舉法一一統計。本題需使用遞推的思想:
設E(n)為n位數中有偶數個3的數字個數,O(n)為n位數中有奇數個3的數字個數。從n位數轉變為n+1位數可以在n位數的基礎上增加一位:
偶數的英文為“Even”, 奇數的英文為“Odd”,在這里“O(n)”可能會和時間復雜度的概念混淆,小心避免理解出錯。
- 如果n位數中有偶數個3,新增一個數位為3,則n+1位數中有奇數個3
- 如果n位數中有偶數個3,新增一個數位為非3,則n+1位數中有偶數個3
- 如果n位數中有奇數個3,新增一個數位為3,則n+1位數中有偶數個3
- 如果n位數中有奇數個3,新增一個數位為非3,則n+1位數中有奇數個3
遞推關系用公式表達如下:
E(n+1)=E(n)*9+O(n)
=>E(n)=E(n-1)*9+O(n-1)
O(n+1)=E(n)+O(n)*9
=>O(n)=E(n-1)+O(n-1)*9
1位數有10個:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 數字3中有奇數個(1個)數字3,其它9個數字中有偶數個(0個)數字3,因此E(1)=9, O(1)=1
,這就是遞推的已知條件,也是我們遞推的起點。但在遞推的時候,數字的第一位是不能為0的,所以遞推到第一位(我們從低位往高位推)時,不是乘9,而是乘8。
當N很大時,數字必定會超過int能夠表達的范圍從而導致溢出,所以在遞歸過程中要不斷的按照題目要求和12345求余以將數字控制在一定范圍內。
通過遞推計算,時間復雜度為O(N)。
代碼示例
#include<iostream>
using namespace std;
int EVEN[1001], ODD[1001]; //Even存儲偶數項,ODD存儲奇數項
int main(){
int N, x=9;
scanf("%d", &N);
EVEN[1]=9; //遞推起點
ODD[1] =1; //遞推起點
for(int i=2; i<=N; i++){
if(i==N) x=8; //遞推到最高項時
EVEN[i]=(EVEN[i-1]*x+ODD[i-1])%12345;
ODD[i] =(EVEN[i-1]+ODD[i-1]*9)%12345;
}
printf("%d", EVEN[N]);
}