CF1157A-Reachable Numbers题解

mac2022-06-30  79

原题地址


题目大意:有一个函数\(f(x)\),效果是将\(x+1\)后,去掉末尾所有的\(0\),例如:

\(f(599)=6\),因为\(599+1=600→60→6\)

\(f(7)=8\),因为\(7+1=8\)

\(f(9)=1\),因为\(9+1=10→1\)

\(f(10099)=101\),因为\(10099+1=10100→1010→101\) 我们可以多次进行函数\(f(x)\)的运算,从而让一个数\(x\)转换为另一个数,例如\(10098\)可以转换为\(102\),因为\(f(f(f(10098)))=f(f(10099))=f(101)=102\)。 你需要做的是给你一个数\(n\),求出\(n\)经过多次函数\(f(x)\)的计算,能转换为几个不同的数(包括自身)?


首先,通过模拟样例,不难得出一个结论:如果\(f(x)\)的结果先前已经得到,那么就代表着所有的答案已经算完。

例如:\(n=1\)时,答案为\(9\),模拟过程如下:

\(f(1)=2\)

\(f(2)=3\)

\(f(3)=4\)

\(f(4)=5\)

\(f(5)=6\)

\(f(6)=7\)

\(f(7)=8\)

\(f(8)=9\)

\(f(9)=1\)

\(f(1)=2\)

\(...\)

不难发现,当我们算到\(f(9)=1\)时,便可以结束计算,因为很显然接着算都是得到之前算过的数,于是我们的代码也就很容易写了。

伪代码:

bool book[];//桶,用于判断某个数是否已经算过 int f(int n)//f函数 { n++; while(!(n)) n/=10; return n; } int main() { for(;!book[n];n=f(n))//核心代码 { book[n]=true; ans++; } }

但是,以上的代码有一个严重的错误:book数组是要开到n级别的,而\(n \le 10^9\),很显然开这么大会MLE,于是我们的\(STL::map\)就派上用场啦!

\(STL::map\)来代替桶,这样就可以防止空间爆炸了。

代码如下:

#pragma GCC diagnostic error "-std=c++11" #include <cstdio> #include <map> using namespace std; template<class T>void r(T &a)//快读 { T s=0,w=1;a=0;char ch=getc(stdin); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getc(stdin);} while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getc(stdin);} a=w*s; } template<class T,class... Y>void r(T& t,Y&... a){r(t);r(a...);} int f(int n) { n++; while(!(n)) n/=10; return n; } map<int,bool>book; int main() { int n,ans=0; r(n); for(;!book[n];n=f(n)) { book[n]=true; ans++; } printf("%d",ans); return 0; }

转载于:https://www.cnblogs.com/Naive-Cat/p/10779661.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)