6 条题解

  • 8
    @ 2022-8-18 22:01:38

    100分做法

    楼下打表是真的不至于

    #include<bits/stdc++.h>
    using namespace std;
    short t;
    int ans,x; // ans用来计算答案,x用来计算最高位的那个数字
    string n,e,nulll; // 这里n用字符串记比较方便后面的计算,e用来计算一个判断字符串,nulll存储一个空字符串,方便e归零(但不是真的变成'0')
    int main(){
        cin>>t;
        for(short i=1;i<=t;i++){
            ans=0;
            cin>>n;
            int len=n.length();
            ans+=(len-1)*9;
            /* 找规律可以发现:
               1≤n≤9(个位)时,最多ans为9(9*1)
               10≤n≤99(十位)时,最多ans为18(9*2)
               100≤n≤999(百位)时,最多ans为27(9*3)
               ···
               也就是说ans至少为(它的位数-1)*9
            */
            x=n[0]-'0'; // 计算最高位的那个数字
            ans+=x-1; // 最高位为x,观察上面的规律可以发现答案还包括(最高位-1)个
            /* 比如:34567
               按照ans+=(len-1)*9得到ans已经为36
               很明显,11111 22222 33333 也是特殊数字
               一共有3个(x个)
               但是如果数字是32569,则一共有x-1个
               所以保险起见这里先加上x-1个,最后一个数字在后面判断
            */
            e=nulll; // 字符串e归零。
            for(int j=0;j<len;j++){ // 创造出一个每一位都一样的特殊数字
                e+=n[0];
                /* 继续按上面34567的例子说
                   当数字最高位是3并且一共有5位时,创建的数字就会是5位的3···3
                   也就是33333
                */
            }
            if(n>=e)++ans;
            /*
               然后由于'0'~'9'是按照字典序排列的,所以直接按字典序比较n和e的大小就行了
               比较出来如果n>=e(34567≥33333)就说明还包括e(33333)
               ans最后再+1就行了
            */
            cout<<ans<<"\n";
        }
        return 0;
    }
    

    精简无注释版

    #include<bits/stdc++.h>
    using namespace std;
    short t;
    int ans,x;
    string n,e,nulll;
    int main(){
        cin>>t;
        for(short i=1;i<=t;i++){
            ans=0;
            cin>>n;
            int len=n.length();
            ans+=(len-1)*9;
            x=n[0]-'0';
            ans+=x-1;
            e=nulll;
            for(int j=0;j<len;j++){
                e+=n[0];
            }
            if(n>=e)++ans;
            cout<<ans<<"\n";
        }
        return 0;
    }
    
    • @ 2023-12-17 11:00:39

      某语言学得真好!(—__—)

  • 1
    @ 2024-1-17 12:05:14

    《暴力做法》

    #include<bits/stdc++.h>
    using namespace std;
    int t;
    string n;
    bool f(string a)
    {
        int c=a.length();
        for(int i=1;i<c;i++)
        {
            if(a[0]>a[i])
            {
                return 1;
            }
            if(a[i]>a[0])
            {
                break;
            }
        }
        return 0;
    }
    

    别想抄哦!

    int main()
    {
    cin>>t;
    for(int i=1;i<=t;i++)
    {
    cin>>n;
    cout<<n[0]-'0'-f(n)+9*(n.length()-1)<<endl;
    }
    return 0;
    }
    
    
    • 1
      @ 2022-11-19 9:19:51

      我的想法是枚举每一个特殊数字,直到比n大为止。

          for (short i = 0 ; i < t ; i++)
          {
              cin >> n;
              special_num = 1;
              ed = 1;
              sum = 0;
              while (special_num <= n)
              {
                  if (special_num % 10 == 0)
                  {
                      ed = ed * 10 + 1;
                      special_num = ed;
                  }
                  sum++;
                  special_num += ed;
              }
              cout << sum << endl;
          }
      
      • 1
        @ 2022-9-25 22:33:52

        😄 如果按照题目叙述遍历是不行的,因为1~n之间的数字都需要逐个判断,而n的范围是10910^{9},字符串做法也无从谈起,所以只能反向构造,刚开始我是这么写的:

        if (n > 1000000000) // 是一个10位数 
        {
        	cnt = 81;
        	for (int i = 1111111111; i <= n; i += 1111111111)
        	{
        		cnt ++;
        	}
        }
        else if (n > 100000000) // 是一个9位数 
        {
        	cnt = 72;
        	for (int i = 111111111; i <= n; i += 111111111)
        	{
        		cnt ++;
        	}
        }
        

        没错的啦,从大往小写,写到最后就能看出有没有写错~就是这样,不要忘记给cnt清0:

        else // 是一个1位数 
        {
        	for (int i = 1; i <= n; i += 1)
        	{
        		cnt ++;
        	}
        } 
        cout << cnt << endl;
        cnt = 0;
        

        这样的话可以AC,但是本质上还是枚举,算不得构造,可以找到一些规律,然后用数组的特性来构造,9个为一轮,本轮的数依靠上一轮的数得出:

        n 1 2 3 4 5 6 7 8 9
        特殊数字的个数 1 2 3 4 5 6 7 8 9
        n 11 22 33 44 55 66 77 88 99
        特殊数字的个数 10 11 12 13 14 15 16 17 18
        n 111 222 333 444 555 666 777 888 999
        特殊数字的个数 19 20 21 22 23 24 25 26 27
        n 1111 2222 3333 4444 5555 6666 7777 8888 9999
        特殊数字的个数 28 29 30 31 32 33 34 35 36

        以特殊数字出现的个数作为数组下标,可以找到构造方法,注意定义一个p专门递增下标,不要和轮数的循环变量i以及每轮内部递增的循环变量j混起来,这很重要:

        for (int i = 1; i <= 9; i++) 
        {
        	a[++p] = i;
        }
        for (int i = 0; i < 9; i++)
        {
        	for (int j = 1; j <= 9; j++)
        	{
        		a[++p] = a[i * 9 + j] * 10 + j;
        	}
        }
        

        然后就可以看看输入的n落在了哪个值内,来找数组下标,也即特殊数字出现的次数

        while (t--)
        {
        	cin >> n;
        	for (int i = 1; i <= 100; i++) 
        	{
        		if (a[i] > n)
        		{
        			cout << i - 1 << endl;
        			break; 
        		}
        	}
        }
        

        因为n最大为10910^{9},所以i不会超过81,给100够够的了。

      • -2
        @ 2022-8-1 15:06:43

        刚看到这道题的时候有点难受,划到最下面发现数据好大啊,要是像往常那样%10再/10我估计会超时,所以,让我们快乐的打表吧 但是这个表可不能乱打,有些太久的打表方法肯定不能用,不然要等好久 所以,不知道大家发现了没有,对于1-9来说,+1就可以让ans+1,而11-110中,加11就可以让ans+1,111-1110以及后面则以此类推,但10要特判,输出9,ans在打表时也要手动改,下面是AC打表代码。

        #include <bits/stdc++.h>
        using namespace std;
        long long t,ans;
        bool flag=true;
        long long n;
        int main(){
            cin>>t;
            while(t--){
                cin>>n;
                ans=0;
                if(n<10)ans=n;
                if(n==10)ans=9;
                if(n>=11&& n<22)ans=10;
                if(n>=22&& n<33)ans=11;
                if(n>=33&& n<44)ans=12;
                if(n>=44&& n<55)ans=13;
                if(n>=55&& n<66)ans=14;
                if(n>=66&& n<77)ans=15;
                if(n>=77&& n<88)ans=16;
                if(n>=88&& n<99)ans=17;
                if(n>=99&& n<110)ans=18;
                if(n>=111&& n<222)ans=19;
                if(n>=222&& n<333)ans=20;
                if(n>=333&& n<444)ans=21;
                if(n>=444&& n<555)ans=22;
                if(n>=555&& n<666)ans=23;
                if(n>=666&& n<777)ans=24;
                if(n>=777&& n<888)ans=25;
                if(n>=888&& n<999)ans=26;
                if(n>=999&& n<1110)ans=27;
                if(n>=1111&& n<2222)ans=28;
                if(n>=2222&& n<3333)ans=29;
                if(n>=3333&& n<4444)ans=30;
                if(n>=4444&& n<5555)ans=31;
                if(n>=5555&& n<6666)ans=32;
                if(n>=6666&& n<7777)ans=33;
                if(n>=7777&& n<8888)ans=34;
                if(n>=8888&& n<9999)ans=35;
                if(n>=9999&& n<11110)ans=36;
                if(n>=11111&& n<22222)ans=37;
                if(n>=22222&& n<33333)ans=38;
                if(n>=33333&& n<44444)ans=39;
                if(n>=44444&& n<55555)ans=40;
                if(n>=55555&& n<66666)ans=41;
                if(n>=66666&& n<77777)ans=42;
                if(n>=77777&& n<88888)ans=43;
                if(n>=88888&& n<99999)ans=44;
                if(n>=99999&& n<111110)ans=45;
                if(n>=111111&& n<222222)ans=46;
                if(n>=222222&& n<333333)ans=47;
                if(n>=333333&& n<444444)ans=48;
                if(n>=444444&& n<555555)ans=49;
                if(n>=555555&& n<666666)ans=50;
                if(n>=666666&& n<777777)ans=51;
                if(n>=777777&& n<888888)ans=52;
                if(n>=888888&& n<999999)ans=53;
                if(n>=999999&& n<1111110)ans=54;
                if(n>=1111111&& n<2222222)ans=55;
                if(n>=2222222&& n<3333333)ans=56;
                if(n>=3333333&& n<4444444)ans=57;
                if(n>=4444444&& n<5555555)ans=58;
                if(n>=5555555&& n<6666666)ans=59;
                if(n>=6666666&& n<7777777)ans=60;
                if(n>=7777777&& n<8888888)ans=61;
                if(n>=8888888&& n<9999999)ans=62;
                if(n>=9999999&& n<11111110)ans=63;
                if(n>=11111111&& n<22222222)ans=64;
                if(n>=22222222&& n<33333333)ans=65;
                if(n>=33333333&& n<44444444)ans=66;
                if(n>=44444444&& n<55555555)ans=67;
                if(n>=55555555&& n<66666666)ans=68;
                if(n>=66666666&& n<77777777)ans=69;
                if(n>=77777777&& n<88888888)ans=70;
                if(n>=88888888&& n<99999999)ans=71;
                if(n>=99999999&& n<111111110)ans=72;
                if(n>=111111111&& n<222222222)ans=73;
                if(n>=222222222&& n<333333333)ans=74;
                if(n>=333333333&& n<444444444)ans=75;
                if(n>=444444444&& n<555555555)ans=76;
                if(n>=555555555&& n<666666666)ans=77;
                if(n>=666666666&& n<777777777)ans=78;
                if(n>=777777777&& n<888888888)ans=79;
                if(n>=888888888&& n<999999999)ans=80;
                if(n>=999999999&& n<1111111110)ans=81;
                cout<<ans<<endl;
            }
            return 0;
        }
        

        这个打表呢是不知道怎么优化才这样做的,但是如果有更优解法的话望各位dalao指教

      • -6
        @ 2022-4-24 16:44:54

        写题解请注意

        鼓励大家写题解,但注意题解格式。

        题解一定要有思路解析或代码注释,能否让别人理解你的思路

        也是你的能力的检验,不要只放无意义的代码给大家复制,那就失去了做题的初心。

        给代码两端加上这个会舒服一些

        ```cpp

        你的代码

        ```

        </span>

        这个点在键盘的左上角tab上面那个键,注意切换输入法

        #include<iostream>
        using namespace std;
        int main()
        {
            int n;
            cin>>n;//这是一个注释
            return 0;
        } 
        

        请注意严禁抄袭题解,写题解不要只放代码,需加上你的思路或代码注释。

        抄袭题解一经发现直接取消成绩。

        题解被删除的可能

        1. 代码不符合格式规范
        2. 没有思路讲解或者没有注释,
        3. 无意义的题解

        大家携手共同维护一个良好的编程环境,如果一经发现,多次作乱。可能会被管理员拉黑,请注意,一旦拉黑即失去登陆资格。

        • 1

        信息

        ID
        1275
        时间
        1000ms
        内存
        256MiB
        难度
        5
        标签
        递交数
        201
        已通过
        84
        上传者