【Acwing338】计数问题题解

题目描述

【Acwing338】计数问题题解_第1张图片

【Acwing338】计数问题题解_第2张图片举个栗子+分类讨论

求a~b中x的个数,可以转换为1~b中x的个数减去1~a-1中x的个数

所以核心是求1~n中x的个数,可以转换为求x在1~n中每一个数的每一位上出现的次数的和

假设要求1~abcdefg(这是一个七位数)中x=1的个数,可以求1在个位数上出现的总次数n1、1在十位数上出现的总次数n2、1在百位数上出现的总次数n3......以此类推,然后把n1、n2...求和,即为1~n之间所有数字1出现的总次数,同理其它数字0,2,3,...,9,也用类似的方式加起来即可。

现在以“1在第4位上出现的总次数”为例,进行分类讨论

1<=xxx1yyy<=abcdefg

如果xxx=0~abc-1,那么yyy可以取遍000~999,总共的情况数为:1000*abc

特例:如果在这里是求0在第4位上出现的总次数,那么xxx不能为0,此时总情况为999*abc

如果xxx=abc:

如果d<1,此时1不可能在第4位上出现

如果d=1,此时yyy可以取遍000~efg,总共efg+1种情况

如果d>1,此时yyy可以取遍000~999,总共1000种情况

所以当n=abcdefg时,“1在第4位上出现的总次数”就是1000*abc+efg+1+1000

当求1在其他位上出现的总次数时,只需要和上述类比即可

同理,求其他数字出现的次数时,和重复上述方法即可(注意上述说的x=0的一个小特殊情况)

代码与注释

#include
#include
using namespace std;
typedef long long LL;
int a,b;
int power10(int i)//计算10的i次方
{
    int res=1;
    while(i)
    {
        res*=10;
        i--;
    }
    return res;
}
LL count(int n,int x)//统计1~n中x出现了多少次
{
    if(!n)return 0;
    LL res=0;
    int cnt=0;
    int temp=n;
    while(temp)
    {
        temp/=10;
        cnt++;
    }
    for(int i=0;ix)res+=r;
    }
    return res;
}
int main()
{
    while(cin>>a>>b,a||b)
    {
        if(a>b)swap(a,b);
        for(int i=0;i<=9;i++)
        cout<

 

你可能感兴趣的:(算法,算法,数据结构,c++,acwing)