杭电ACM 2089:不要62

原创作品 转载请注明出http://blog.csdn.net/always2015/article/details/46915901

这里写图片描述

这个题目的意思就是从给定的一个数字范围内,求出不包含不吉利数字4或者62的数字个数。所以主要问题是如何判断该数是不是吉利数字,我的想法是对于一个数字,一位一位的进行判断该位是否为4或者连续两位是否为62。这个很容易实现,一开始我写的代码如下:

#include <iostream>
using namespace std;
int main(void)
{
    int n,m,temp1,temp2;
    int total_num,unlucky_num=0,flag=0,flag1=0;
    while(cin>>n>>m&&n>0&&n<1000000)
    {
        total_num=m-n+1;//计算区间号码总数
        for(int i=n; i<=m; i++)
        {
            /*****检验是否含有62****/
            flag=0;//flag用来对62这个情况的标记,在检验每个i前都要初始化
            temp1=i;
            while(temp1>=2)
            {
                //出现2的时候,做一个标记
                if(temp1%10==2)
                {
                    ++flag;
                    //如果;连续出现两次2,则只计算一次,防止错漏如622这样的类型数字
                    if(flag==2)
                    {
                        flag=1;
                    }
                }
                else if(temp1%10==6)//出现6做判断
                {
                    ++flag;
                    if(flag==2)
                    {
                        ++unlucky_num;
                        flag=0;
                        flag1=1;
                        break;//符合条件就挑出循环
                    }
                    else
                        flag=0;//当出现6的是时候,如果还不是62,那么这次就舍去,flag重新置0,这个也可以排除了66这种可能
                }
                else
                    flag=0;//这个标志主要是当出现682这样的数时候,出现错误
                temp1=temp1/10;//进入该数的下一位进行判断
            }
            //如果62已经判断成功了,下面就不需要判断了,如果不做次此判断有些数字会统计2次,比如462
            if(flag1==1)
            {
                flag1=0;
                continue;
            }

            /****检验是否有4*****/
            temp2=i;
            while(temp2>=4)
            {
                if(temp2%10==4||temp2==4)
                {
                    ++unlucky_num;
                    break;//符合条件就跳出循环
                }
                else
                    temp2=temp2/10;//进入该数的下一位进行判断
            }
        }
        //格式输出
        cout<<total_num-unlucky_num<<endl;
        //下面变量需要重新初始化,保证下一个循环正确
        unlucky_num=0;
    }
    return 0;
}

按照上面我刚开始的方法写的话,提交会给出的错误为Time Limit Exceeded,说明已经超出了时间限制,尽管这样做自我感速度也是很快,但是无法通过还是不行的,然后在网上查看了一下资料,上面说因为题目要求只在1到1000000之间进行,所以不妨可以先遍历一遍这个范围把不吉利的数字做个标记保存在一个数组中。当新输入的范围来时,就查看这个范围内的数据的标志,就可以在单位时间得出该数是否是不吉利的数字。下面给出我的AC代码,就是在上述代码修改而来的。

#include <iostream>
#include<string.h>
using namespace std;

//因为题目中0<n<=m<1000000,所以可以直接将1到1000000是否吉利做标记
int a[1000001];//因为申请的内存很大,必须做全局变量。如果放在main里面,就会出现栈溢出
int main(void)
{

    int n,m,temp1,temp2;
    int total_num,unlucky_num=0,flag=0;

   //对1到1000000数做标记,不吉利则标记为1,吉利为0
    memset(a,0,sizeof(a));
    for(int k=1; k<=1000000; k++)
    {
        /*****检验是否含有62****/
        flag=0;//flag用来对62这个情况的标记,在检验每个i前都要初始化
        temp1=k;
        while(temp1>=2)
        {
            //出现2的时候,做一个标记
            if(temp1%10==2)
            {
                ++flag;
                //下面这个判断是为了防止出现622这种情况
                if(flag==2)
                {
                    flag=1;//出现两个2时候,只计算一个2
                }
            }
            else if(temp1%10==6) //出现6做判断
            {
                ++flag;

                if(flag==2)
                {
                    a[k]=1;
                    flag=0;
                    break;//符合条件就挑出循环
                }
                else
                    flag=0;//当出现6的是时候,如果还不是62,那么这次就舍去,flag重新置0,这个也可以排除了66这种可能
            }
            else
                flag=0;//这个标志主要是当出现682这样的数时候,出现错误

            temp1=temp1/10;//进入该数的下一位进行判断

        }

        /****检验是否有4*****/

        temp2=k;
        while(temp2>=4)
        {
            if(temp2%10==4||temp2==4)
            {
                a[k]=1;
                break;//符合条件就跳出循环
            }
            else
                temp2=temp2/10;//进入该数的下一位进行判断
        }
    }


   //对输入的数据范围做判断
    while(cin>>n>>m)
    {
        if(n==0&&m==0)break;
        total_num=m-n+1;//计算区间号码总数
        for(int i=n; i<=m; i++)
        {
            if(a[i]==1)
            {
                ++unlucky_num;//累加
            }

        }
        //格式输出结果
        cout<<total_num-unlucky_num<<endl;
        unlucky_num=0;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值