原題地址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; }