Self-Numbers解题报告
来源:互联网 发布:英版iphone6s支持网络 编辑:程序博客网 时间:2024/05/20 21:18
题目描述:
在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
解题报告:
一来看这道题,认为是一道简单的模拟题,每个数字枚举比它小的所有数,看它是否是self-number,那么,时间复杂度是O(n^2),一看n是10^7就知道这样死定了,于是,我想了一下,例如我检测999999是否是self-number,还需要从1,2,3,4,5……甚至999这些对于999999很小的数开始枚举吗,显然不需要,因为n最大是10^7,所以一个数字所有位加起来最大的是999999(为54),所以,最多从x-54开始枚举就是了,代码如下:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<ctime>
#include<cctype>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
using namespace std;
int s[5005],n,k,num,a[10000005];
inline void scan(int &v)//读入优化
{
v=0;char c=0;int p=1;
while(c<'0'||c>'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0'&& c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
int d(int x)
{
int ans=x;
while(x)
ans+=x%10,x/=10;
return ans;
}
bool check(int x)//检测是否是Self-Number
{
bool flag=true;
for(int i=x>54?x-54:0;i<=x;i++)
if(d(i)==x)flag=false;
return flag;
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++)scan(s[i]);
for(int i=1;i<=n;i++)
if(check(i))
num++,a[num]=i;
cout<<num<<endl;
for(int i=1;i<=k;i++)
printf("%d ",a[s[i]]);
return 0;
}
本来还是比较自信的,其实提交只有60分(超时),于是只有想一想有没有更好的算法了,于是想到了筛法,这样就不需要check函数了,查它是不是只需要O(1)而不是O(54)。提高了效率
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<ctime>
#include<cctype>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
using namespace std;
int s[5005],n,k,num,a[10000005];
bool flag[10000005];
inline void scan(int &v)//读入优化
{
v=0;char c=0;int p=1;
while(c<'0'||c>'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0'&& c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
void d(int x)
{
int ans=x;
while(x)
ans+=x%10,x/=10;
flag[ans]=true;
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++)scan(s[i]);
for(int i=1;i<=n;i++)
{
if(!flag[i])//没被筛
num++,a[num]=i;
d(i);//筛
}
cout<<num<<endl;
for(int i=1;i<=k;i++)
printf("%d ",a[s[i]]);
return 0;
}
语种:C++
- Self-Numbers解题报告
- Pku acm 1316 Self Numbers 解题报告
- [leetcode] 315. Count of Smaller Numbers After Self 解题报告
- [Leetcode] 315. Count of Smaller Numbers After Self 解题报告
- USACO :Runaround Numbers 解题报告
- ZQUOJ1398 Fibonacci Numbers解题报告
- ZQUOJ1403Factoring Large Numbers解题报告
- HDOJ__1058 Humble Numbers 解题报告
- Raising Modulo Numbers 解题报告
- 解题报告:POJ_1338 Ugly Numbers
- [leetcode] 335. Self Crossing 解题报告
- [Leetcode] 335. Self Crossing 解题报告
- POJ 2769 Reduced ID Numbers 解题报告
- pku_1504 Adding Reversed Numbers 解题报告
- poj 1142Smith Numbers(解题报告)
- 1586. Threeprime Numbers 解题报告 URAL
- HDOJ 1058 Humble Numbers解题报告【DP】
- HDU 4722 Good Numbers 解题报告
- Spring Cache与Redis结合使用
- mysql 之 sql 语句 之 数据的增删改查
- Java异常处理
- 计算机基础---时钟
- 常用布局效果02-云资源购买信息展示布局
- Self-Numbers解题报告
- SpringBoot--整合Dubbo
- 源码分析Activity的构成
- CF892E Envy
- windows下修改mysql的root用户的密码,解决1045错误
- 吴恩达deeplearning之CNN—目标检测(1)
- Java
- Kafka的leader选举过程
- 异常类处理