好数 | 第十五届蓝桥杯C++B组

一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位 ⋯ )上的数字是奇数,偶数位(十位、千位、十万位 ⋯ )上的数字是偶数,我们就称之为 “好数”。

给定一个正整数 NN,请计算从 11 到 NN 一共有多少个好数。

输入格式

一个整数 NN。

输出格式

一个整数代表答案。

数据范围

对于 10%10% 的评测用例,1≤N≤1001≤N≤100。
对于 100%100% 的评测用例,1≤N≤1071≤N≤107。

输入样例1:
24
输出样例1:
7
样例1解释

2424 以内的好数有 1,3,5,7,9,21,231,3,5,7,9,21,23,一共 77 个。

输入样例2:
2024
输出样例2:
150
题解:

        直接写是很简单的题目,只要从1遍历到n,再把每个数转变成string,再遍历每一位进行判断,计数即可解出。

        但是,这道题如果简单地写就会TLE。

        发现最大7位数,那我把n分成10000以上以及10000内的话,当n<10000时就直接计算,而n>10000的时候就分成两部分。比如7814893这个数,分成781和4893两个数。并且发现,从第五位合法的10000到19999这之间共625个数,而当前3位合法的情况下才会计算这些数,于是直接从1遍历到780(注意要少1),得到一个cnt1,而cnt1*625+650(1-10000的好数)就是当前阶段的答案。

        但是,781开头的数就没法直接判断,所以要先判断781是否合法,如果合法,则继续判断1-4893(后四位)的好数,得到cnt2,加上则是答案。

        但是(还有但是),最终答案要减去25,原因是当10000和10100之间的数,如果只考虑1-100是有25个合法的数,但是如果放进,比如10087,87是合法的,但是10087是不合法的,所以最终答案要减去25。

代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;

int n=0;
int cnt=0;

int main(){
    cin >> n;
    if(n>=10000){
        int t1=n/10000;
        int cnt1=0;
        for(int i=1;i<=t1-1;i++){
            string s;
            s=to_string(i);
            int t=1;
            for(int j=s.size()-1;j>=0;j--){
                if((s.size()%2==0 && (s[0]-48)%2==1) || (s.size()%2==1 && (s[0]-48)%2==0)){
                    break;
                }
                if((t%2==1 && (s[j]-48)%2==0) || (t%2==0 && (s[j]-48)%2==1)){
                    break;
                }
                t++;
                if(j==0){
                    cnt1++;
                }
            }
        }
        cnt=cnt1*625+650;
        //cout << cnt << "\n";
        bool a=false;
        string s;
        s=to_string(t1);
        int t=1;
        for(int j=s.size()-1;j>=0;j--){
            if((s.size()%2==0 && (s[0]-48)%2==1) || (s.size()%2==1 && (s[0]-48)%2==0)){
                break;
            }
            if((t%2==1 && (s[j]-48)%2==0) || (t%2==0 && (s[j]-48)%2==1)){
                break;
            }
            t++;
            if(j==0){
                a=true;
            }
        }
        if(a){
            int t2=n%10000;
            //cout << t2 << "\n";
            int cnt2=0;
            for(int i=1;i<=t2;i++){
                string s;
                s=to_string(i);
                int t=1;
                for(int j=s.size()-1;j>=0;j--){
                    if((s.size()%2==0 && (s[0]-48)%2==1) || (s.size()%2==1 && (s[0]-48)%2==0)){
                        break;
                    }
                    if((t%2==1 && (s[j]-48)%2==0) || (t%2==0 && (s[j]-48)%2==1)){
                        break;
                    }
                    t++;
                    if(j==0){
                        cnt2++;
                    }
                }
            }
            //cout << cnt2 << "\n";
            cnt+=cnt2;
            cnt-=25;
        }
    }
    else{
        for(int i=1;i<=n;i++){
            string s;
            s=to_string(i);
            int t=1;
            for(int j=s.size()-1;j>=0;j--){
                if((s.size()%2==0 && (s[0]-48)%2==1) || (s.size()%2==1 && (s[0]-48)%2==0)){
                    break;
                }
                if((t%2==1 && (s[j]-48)%2==0) || (t%2==0 && (s[j]-48)%2==1)){
                    break;
                }
                t++;
                if(j==0){
                    cnt++;
                }
            }
        }
    }

    cout << cnt;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值