1. 程式人生 > >CCF NOI1052. Self-Numbers

CCF NOI1052. Self-Numbers

時間限制: 1000 ms  空間限制: 262144 KB  具體限制  

題目描述

在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<=10^7,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<=10^7,1<=K<=5000

題記:

這道題有點麻煩……需要先計算在閉區間[1, N]中Self-Number的數量並輸出,在輸出小於N的a[s1]……a[sk]。

C++程式如下:

#include <iostream>
#include <cstring>

using namespace std;
const int N = 10000000; 
int sncount[N+1];
int sn[N+1];

int self_number(int n)
{
    int sum = n;
    while(n) {
        sum += n % 10;
        n /= 10;
    }
    return sum;
}
 
int main(void)
{
    int n, k, s, count, i, j;
 
    memset(sncount, 0, sizeof(sncount));
 
    cin >> n >> k;
    
    //計算在閉區間[1, N]中Self-Number的數量
    count = 1;
    for(i=1; i<=n; i++) {
        j = self_number(i);
        if(j <= N)
            sncount[j]++;
 
        if(!sncount[i])
            sn[count++] = i;
    }
 
    cout << count - 1 << endl;
    for(i=1; i<=k; i++) {
        cin >> s;
        cout << sn[s] << " ";
    }
 
    return 0;
}