【集训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;
}
posted @ 2017-08-14 10:18  Nanjo  阅读(229)  评论(0编辑  收藏  举报