洛谷 P1900 自我数

题目描述

在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)

 

输入输出样例

输入样例#1: 复制
100 10
1 2 3 4 5 6 7 11 12 13 
输出样例#1: 复制
13
1 3 5 7 9 20 31 75 86 97
思路:模拟+数学。
类似于欧拉筛法。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int cnt,n,k;
int ans[1000010];
bool flag[10000010];
int next(int num){
    int ans=0;
    ans+=num;
    while(num!=0){
        ans+=num%10;
        num/=10;
    }
    return ans;
}
int main(){
    memset(flag,true,sizeof(flag));
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        if(flag[i]){
            ans[++cnt]=i;
            int now=next(i);
            while(now<=n&&flag[now]) {
                flag[now]=false;
                now=next(now);
            }
        }
    printf("%d
",cnt);
    int t=0;
    for(int i=1;i<=k;i++){
        scanf("%d",&t);
        printf("%d ",ans[t]);
    }
}
 
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
原文地址:https://www.cnblogs.com/cangT-Tlan/p/8012513.html