SDUT OJ 1704 数字统计问题

SDUT OJ 1704 数字统计问题

博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/40930259

昨天晚上学弟问了OJ上这个题,群里说不清楚,就写个解题报告吧。

题目大意:

中文题目,就不翻译了-。-

解题思路:

不知道算不算一个典型的数位DP,反正有点那个意思,感觉确实也可以用记忆话搜索,两个差不多的意思。

我找了一下,这个问题好像是算法设计与实验题解上面的一道题,别的OJ上没有,所以就在自己OJ上做了。

大体的思路就是,对于一个数字,比如1342,想要求出每一个数字出自出现的次数,

对于一个n位的十进制数,从一个n位十进制数的由低到高的第i个数位上,总是连续出现10^i个0,然后是10^i个1……一直到10^i个9,9之后又是连续的10^i个0,这样循环出现。找到这个规律,就可以在常数时间内算出第i个数位上每个数字出现的次数。而在第i个数位上,最后再把前导0的数量去掉就是最后要的答案了。

这样最大的时间复杂度是数字位数,也就是log10(n)的复杂度,所以就不会超时了,最后跑了0ms。

吐槽一下宿舍的网,实在是太卡了,写个博客都这么费劲。。。。。真蛋疼。。。

具体的可以看代码,代码中会有部分解释:

#include <stdio.h>
#include <string.h>

int a[10], ans[10], len;
char s[10];

int main()
{
    a[0] = 1;
    for(int i = 1; i < 10; ++i) {
        a[i] = a[i-1]*10; ///a[i]记录 pow(10, i)
    }
    int n = 0;
    scanf("%s", s);///以字符串输入 便于统计长度
    len = strlen(s);
    for(int i = 0; i < len; ++i) {
        n = n*10+(s[i]-'0'); ///计算 n
    }
//    printf("%d\n", n);
    memset(ans, 0, sizeof(ans));
    for(int i = 0; i < len; ++i) {
        int num = s[i]-'0';
        int tmp = n/a[len-i-1];
        ans[num] += n+1-tmp*a[len-i-1];///从左到右 到第i+1位数字不变的前提下,第i+1位为num的数量
        tmp /= 10;
        int j = 0;
        while(j < num) {
            ans[j++] += (tmp+1)*a[len-i-1];
            ///记录当前位置 j 出现的次数
        }
        while(j < 10) {
            ans[j++] += tmp*a[len-i-1];
            ///记录当前位置 j 出现的次数
        }
        ans[0] -= a[len-i-1]; ///去掉前导零的数目
//        printf("%d\n", ans[0]);
    }
    for(int i = 0; i < 10; ++i) {
        printf("%d\n", ans[i]); ///打印结果
    }

    return 0;
}
时间: 2024-10-25 18:53:24

SDUT OJ 1704 数字统计问题的相关文章

SDUT OJ -2892 A

A Time Limit: 60ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 给出n(1<= n && n <= 2*10^6)个字符串,每个字符串只包含小写英文字母,且最多有五个.问这n个字符串中出现次数最多的有多少个. 输入 单组输入.第一行输入一个数字n,接下来n行,每行包含一个字符串. 输出 输出一个数字代表答案. 示例输入 5 aba abb w aba z 示例输出 2 提示 字段树,模板题 #include <iost

sdut 3-5 学生成绩统计

3-5 学生成绩统计 Time Limit: 1000MS Memory limit: 65536K 题目描述 通过本题目练习可以掌握对象数组的用法,主要是对象数组中数据的输入输出操作. 设计一个学生类Student它具有私有的数据成员:学号.姓名.数学成绩.英语成绩.计算机成绩:具有公有的成员函数:求三门课总成绩的函数int sum();求三门课平均成绩的函数double average();输出学生基本信息.总成绩和平均成绩的函数void print():设置学生数据信息的函数voidset

zznu 1255 数字统计(数位DP, 数学方法)

最近在学数位DP, 感觉还是满有收获的! 做了几个题之后想起来自己OJ上曾经做的一道题,以前是用数学方法写的,现在改用数位DP来写了一遍. 题目: 1255: 数字统计 时间限制: 1 Sec  内存限制: 128 MB提交: 31  解决: 4[提交][状态] 题目描述 一本书的页码从自然数1 开始顺序编码直到自然数n.书的页码按照通常的习惯编排, 每个页码都不含多余的前导数字0.例如,第6 页用数字6 表示,而不是06 或006 等.数 字计数问题要求对给定书的总页码n,计算出书的全部页码中

SDUT OJ 3045 迷之图论 (树的直径)

题目地址:SDUT OJ 3045 这题比赛的时候想的差不多..但是总是觉得不对..写了一次就没再写,然后删了..当时没想到的是第二次求出来的就是最长链..当时想到的两次bfs找最大值(这一种方法其实结果也对..TAT..),还有找到点后在回溯减去重点等等..但总觉得好像都不太对...赛后才知道这题原来是树的直径.....牡丹江区域现场赛的时候遇到过,不过赛后也没看... 找树的直径的方法其实就是先任取一点进行bfs,找到最远的一点,这时最远的一点肯定是最长链端点之一,然后再从这一最远点开始bf

数字统计(0)&lt;P2010_1&gt;

数字统计   (two.pas/c/cpp) [问题描述] 请统计某个给定范围[L, R]的所有整数中,数字 2 出现的次数.  比如给定范围[2, 22],数字 2 在数2中出现了 1次,在数 12中出现 1 次,在数 20 中出现 1 次,在数 21 中出现 1 次,在数 22 中出现 2 次,所以数字 2 在该范围内一共出现了 6次.  [输入] 输入文件名为 two.in.  输入共 1 行,为两个正整数 L 和 R,之间用一个空格隔开.  [输出] 输出文件名为 two.out.  输

一款纯css3实现的数字统计游戏

今天给大家分享一款纯css3实现的数字统计游戏.这款游戏的规则的是将所有的数字相加等于72.这款游戏的数字按钮做得很美观,需要的时候可以借用下.一起看下效果图: 在线预览   源码下载 实现的代码. html代码: <h1> CSS Counter Game</h1> <section> <h2> Pick the numbers that add up to 72:</h1> <input id="a" type=&q

AC日记——数字统计 openjudge 1.5 41

41:数字统计 总时间限制:  1000ms 内存限制:  65536kB 描述 请统计某个给定范围[L, R]的所有整数中,数字2出现的次数. 比如给定范围[2, 22],数字2在数2中出现了1次,在数12中出现1次,在数20中出现1次,在数21中出现1次,在数22中出现2次,所以数字2在该范围内一共出现了6次. 输入 输入共 1 行,为两个正整数 L 和 R,之间用一个空格隔开. 输出 输出共 1 行,表示数字 2 出现的次数. 样例输入 样例 #1: 2 22 样例 #2: 2 100 样

数字统计问题

1.      一本书的页码从自然数1开始顺序编码直到自然数n.书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0.例如第6页用6表示而不是06或006.数字统计问题要求对给定书的总页码,计算出书的全部页码中分别用到多少次数字0,1,2,3,.....9. 思路:对于n位数,例如3位数,000-999,出现0,1,2...9的次数相同,记每个数字出现的次数为avg,这10个数字出现的总次数为sum=10*avg. 而n位数共有10^n个数,每个具体的数对于sum的贡献为n次. 得到:10

SDUT OJ 1221 亲和数 (找出某个数n所有的因子数,只需要暴力:2-&gt;sqrt(n) 即可 )

亲和数 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 如果a的因子和等于b,b的因子和等于a,且a≠b,则称a,b为亲和数对. 比如220的所有真约数(即不是自身的约数)之和为: 1+2+4+5+10+11+20+22+44+55+110=284. 284的所有真约数和为: 1+2+4+71+142=220. 你的任务就编写一个程序,判断给定的两个数是否是亲和数. 输入 输入数据第一行包含一个数M,接下有M行,每行一个实例,