P1239 计数器数学规律

面对这样一共题第一想法是模拟,但是数据大的话容易超时,那么下面我就讲解一下对于大数据的情况下这道题如何去写。 

对于十分大的数据要我们求0-9数字出现的次数,那么在不会用算法的情况下可以看看有没有规律。了解去取余的话,我们可以知道后四位会形成一定的规律,那么我们就来看看1-9999的数字出现情况。

#include<bits/stdc++.h>
using namespace std;
int a[10];
void f(int y){ //计算一个数中每个数码出现次数
    while(y>0) a[y%10]++,y=y/10;
}
int main(){
    for(int i=1;i<=9999;i++)
	{
		f(i);	
	}
	for(int i=0;i<10;i++)
	{
		cout<<a[i]<<endl;
	}
    return 0;
}

2889
4000
4000
4000
4000
4000
4000
4000
4000
4000
结果

再来看看10000-19999,20000-29999;

#include<bits/stdc++.h>
using namespace std;
int a[10];
void f(int y){ //计算一个数中每个数码出现次数
    while(y>0) a[y%10]++,y=y/10;
}
int main(){
    for(int i=10000;i<=19999;i++)
	{
		f(i);	
	}
	for(int i=0;i<10;i++)
	{
		cout<<a[i]<<endl;
	}
    return 0;
}
4000
14000
4000
4000
4000
4000
4000
4000
4000
4000

20000-29999

4000
4000
14000
4000
4000
4000
4000
4000
4000
4000

我们可以发现1-9999,在大于9999的时候每个数字出现了4000次,但10000-10001-10258;可以看到1每次都存在所以1是被计算了10000次的所以对于20000-29999,30000-39999,2,3分别被计算了10000次由此规律我们就能求极大值的0-9出现的次数。

距离一个数字36669000

第一步:判断这个数是否大于10000;小于10000直接计算大于一万按照上面方法计算

大于10000;

1.因为第一个1-9999,出现次数0不规律,我们单独计算。

2.计算在大于9999,的时候有多少个1-9999;用36669000/10000可以计算等于3666,但是我们发现366669000  36660000-366669999,不是一共完整的1-9999,所以我们这里也需要单独计算。那么我们有的完整的段数就只有(36-1)个1-9999.

3.计算1-3666出现的次数

理由:20000-29999,30000-39999,40000-49999,2,3,4分别被多计算了10000次,说明前面的数需要单独计算;

4.计算3665个1-9999中0-9的个数上面提到每个数都有4000个所以我们直接4000*(3666-1)

下面是完整代码展示

#include<iostream>
using namespace std;
int a[10];
//计算每个数字中0-9的个数
void js(int i) {
    while (i > 0) {
        a[i % 10]++;
        i=i/10;
    }
}
int main() {
    int n,x,m;
    cin>>n;
     //根据条件2计算有多少个1-9999
     x = n/10000;//n包含多少个1-9999
    if (n<10000) {
        for (int i = 1; i <= n; i++) {
            js(i);
        }
    } else {
        //对于大于10000的数,根据条件1,计算1-9999
        for (int i = 1; i <10000; i++) {
            js(i);
        }
        //的
        //为什么x-1上面也有解释
        for (int i = 1;i<=x-1; i++) {
            int b[10] = {0}; //临时数组用于存储当前段的数字出现次数
            //根据条件三,计算前面的数字,20000-29999,30000-39999,40000-49999,2,3,4分别被多计算了10000次
               m=i;
            while (m>0) {
                b[m%10]++;
                m/=10;
            }
            //多计算了10000所以这里乘以10000
            for (int j =0; j<10; j++) {
                a[j]+=b[j]*10000;
            }
        }
        //条件4计算3665个1-9999中0-9的个数
        for (int j=0;j<=9;j++) {
           a[j]+=4000*(x-1);
        }
        for(int i=x*10000;i<=n;i++)
        {
        js(i);
        }
    }
    // 输出每个数字(0-9)的出现次数
    for (int i = 0; i < 10; i++) {
       cout<<a[i]<<endl;
    }
    return 0;
}

大致思路就是这样,注意细节就好。

总结,对于大数据像这样的,极大可能有规律,多模拟找找规律就好

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

关于不上作者榜就原神启动那件事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值