CCF NOI1052. Self-Numbers (C++)
1052. Self-Numbers
題目描述
在1949年印度數學家D. R. Daprekar發現了一類稱作Self-Numbers的數。對於每一個正整數n,我們定義d(n)為n加上它每一位數字的和。例如,d(75)=75+7+5=87。給定任意正整數n作為一個起點,都能構造出一個無限遞增的序列:n, d(n), d(d(n)), d(d(d(n))), . . . 例如,如果你從33開始,下一個數是33+3+3=39,再下一個為39+3+9=51,再再下一個為51+5+1=57,因此你所產生的序列就像這樣:33, 39, 51, 57, 69, 84, 96, 111, 114, 120, 123, 129, 141, . . . 數字n被稱作d(n)的發生器。在上面的這個序列中,33是39的發生器,39是51的發生器,51是57的發生器等等。有一些數有超過一個發生器,如101的發生器可以使91和100。一個沒有發生器的數被稱作Self-Number。如前13個Self-Number為1, 3, 5, 7, 9, 20, 31, 42, 53, 64, 75, 86, 97。我們將第i個Self-Number表示為a[i],所以a[1]=1, a[2]=3, a[3]=5. . .
輸入
輸入包含整數N、K、s1. . . sk,其中1<=N<=107,1<=K<=5000,以空格和換行分割。
輸出
在第一行你需要輸出一個數,這個數表示在閉區間[1, N]中Self-Number的數量。第二行必須包含以空格劃分的K個數,表示a[s1]. . a[sk],這裡保證所有的a[s1]. . a[sk]都小於N。(例如,如果N=100,sk可以為1-13,但不能為14,因為a[14]=108>100)
樣例輸入
100 10
1 2 3 4 5 6 7 11 12 13
樣例輸出
13
1 3 5 7 9 20 31 75 86 97
資料範圍限制
1<=N<=107,1<=K<=5000
C++程式碼
#include <iostream>
#include <cmath>
#include <cstring>
#include <cassert>
using namespace std;
const int MAX_N = 10000000;
const int MAX_K = 5000;
int SelfNumbersCount[MAX_N+1];
int SelfNumbers[MAX_N+1];
int getdn(int n)
{
int dn = n;
while(n > 0)
{
dn += n % 10;
n /= 10;
}
return dn;
}
int main(void)
{
int N, K;
cin >> N >> K;
// assert(N>=1 && N <= MAX_N);
// assert(K>=1 && K <= MAX_K);
memset(SelfNumbersCount, 0, sizeof(SelfNumbersCount));
int numOfSelfNumbers = 1;
for(int n=1; n<=N; n++)
{
int dn = getdn(n);
if(dn <= N)
{
SelfNumbersCount[dn]++;
}
if(!SelfNumbersCount[n])
{
SelfNumbers[numOfSelfNumbers++] = n;
}
}
cout << numOfSelfNumbers-1 << endl;
int sk;
for(int k=1; k<=K; k++)
{
cin >> sk;
cout << SelfNumbers[sk] << " ";
}
cout << endl;
return 0;
}