原题地址c++
题目大意:有一个函数\(f(x)\),效果是将\(x+1\)后,去掉末尾全部的\(0\),例如:数组
\(f(599)=6\),由于\(599+1=600→60→6\)函数
\(f(7)=8\),由于\(7+1=8\)spa
\(f(9)=1\),由于\(9+1=10→1\)c++11
\(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)\)的计算,能转换为几个不一样的数(包括自身)?code
首先,经过模拟样例,不可贵出一个结论:若是\(f(x)\)的结果先前已经获得,那么就表明着全部的答案已经算完。get
例如:\(n=1\)时,答案为\(9\),模拟过程以下:io
\(f(1)=2\)class
\(f(2)=3\)test
\(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%10)) 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%10)) 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; }