CF1157A-Reachable Numbers題解

原題地址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;
}
相關文章
相關標籤/搜索