【集訓Day1 測試】奇怪數

奇怪數(odometer)
【題目描述】
一個正整數Z是奇怪數,當且僅當滿足的條件是:Z的所有數字中,只有一個數字不同於其他數字。例如:33323、110 都是奇怪數,而 9779、5555 都不是奇怪數。給出兩個正整數 X 和 Y,滿足 100 <= X <= Y <= 10^16,請問區間[X,Y]內有多少個奇怪數?
【輸入格式】odometer.in
一行,兩個整數,X 和 Y。
【輸出格式】odometer.out
一個整數。【輸入樣例】
110 133
【輸出樣例】
13
【樣例解釋】
110,112,113,114,115,116,117,118,119,121,122,131,133 都是奇怪數。
【解題思路】
基本思路是枚舉,但是如果按照正常方法進行枚舉,那麼依照本題的數據範圍,必然會超過時間限制。顯然,需要另外尋找一條路進行枚舉。
根據題面可知,奇怪數是由a,b兩個數字組成,但是其中b只能出現一次。所以,我們可以嘗試枚舉a和b,構成奇怪數。在構成奇怪數之後,判斷是否在x和y的範圍內即可。
【解題反思】

  • 可以嘗試從問題的另一面入手解決問題。
  • 注意奇怪數的定義,由兩個數字組成,但是其中有一個數字只能出現一次,9559,633663這些就不是奇怪數。

【參考程序】

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long len,x,y;
long long count(long long num)
{
    string st="",s="";
    int ansc=0;
    while (num!=0)
    {
        st=char(num%10+48)+st;
        num/=10;
    }//將數字轉化爲字符串 以便求出長度 
    len=st.size(); 
    for (int i=3;i<=len;i++)//枚舉奇怪數的長度 
        for (char j='0';j<='9';j++)//枚舉奇怪數中重複出現的數字 
        {
            s="";
            for (int k=0;k<i;k++) s+=j;//填充奇怪數 
            for (char l='0';l<='9';l++)//枚舉奇怪數中只出現一次的數字 
                if (j!=l)//兩數不相同纔有意義 
                for (int m=0;m<i;m++)//枚舉奇怪數中只出現一次的數字的位置 
                {
                    s[m]=l;//填充 
                    if (s[0]!='0'&& (s<=st||i<len)) ansc++;//判斷是否在範圍內 
                    s[m]=j;
                }
        }
    return ansc;
}
int main()
{
    freopen("odometer.in","r",stdin);
    freopen("odometer.out","w",stdout);
    cin>>x>>y;
    cout<<count(y)-count(x-1);//利用子程序求出100~y之間的奇怪數,再求出 100~(x-1)的奇怪數
    //兩者相減即爲x~y的奇怪數 
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章