输入包括一个整数n(1 ≤ n ≤ 1,000,000,000)
输出包括一行10个整数,即0~9这些数字在页码中出现的次数,以空格分隔。行末无空格。
999
189 300 300 300 300 300 300 300 300 300
//从各位开始对n的每一位进行判断
#include <iostream>
#include <vector>
using namespace std;
int getCount(int n, int t)
{
if (n < 1 || t < 0)
return -1;
int cnt = 0,len=0;
int k = 1;
int j = n;
while (j)
{
j = j / 10;
++len;
}
for (int i = 0; i < len; ++i)
{
if (t>0)
{
if ((n / k) % 10 < t)
cnt += (n / (k*10))*k;
else if ((n / k) % 10 == t)
cnt += (n / (k * 10))*k + n%k + 1;
else
cnt += (n / (k * 10) + 1)*k;
}
else
{
if ((n / k) % 10 == t)
cnt += (n / (k * 10) - 1)*k + n % k + 1;
else
cnt += (n / (k * 10))*k;
}
k = k * 10;
}
return cnt;
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < 10; ++i)
{
if (i == 0)
cout << getCount(n, i);
else
cout << " " << getCount(n, i);
}
cout << endl;
return 0;
} 逐位求解每个数字该位上出现的次数,累加到数组中。
#include
using namespace std;
int main(){
int n,i,j;
cin>>n;
int tmp[10]={0};
for(i=1;j=n/i;i*=10){
int high=j/10;
int res=j%10;
for(int k=0;k<10;k++)
tmp[k]+=i*high;
for(int k=0;k<res;k++)
tmp[k]+=i;
tmp[res]+=n%i+1;
tmp[0]=tmp[0]-i/10;//0的特殊处理
}
tmp[0]=tmp[0]-i/10;
for(int i=0;i<9;i++)
cout<<tmp[i]<<" ";
cout<<tmp[9];
return 0;
}
def find(num):
# 计算每个数字, 在每一位上出现的次数.
res = [0] * 10 # 结果
digit = 1 # 个位
while True:
low = num % digit
cur = (num % (10 * digit)) / digit
high = num / (10 * digit) # 将数字分割, 例如 digit为100时, 表示百位. 12345 将有 high = 12, cur = 3, low = 45
if cur == 0 and high == 0:
break
for i in range(10): # 从0到9, 计算i在digit位出现的次数.
if i < cur:
if i == 0: # 这里主要是因为 0 不能作为数字的开头.
res[i] += high * digit
else:
res[i] += (high+1) * digit
elif i == cur:
if i==0:
res[i] += (high-1) * digit + low + 1
else:
res[i] += high * digit + low + 1
else:
if i == 0:
res[i] += (high-1) * digit
else:
res[i] += high * digit
digit *= 10 # 下一位
return res
num = int(raw_input())
res = find(num)
print ' '.join(map(str, res))
//提供一种简单的思路
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = "0123456789";
while(scanner.hasNext()){
int n = scanner.nextInt();
int[] nums = new int[10];
for(int i=1;i<=n;i++){
char[] c = new String(i+"").toCharArray();
for(int j=0;j<c.length;j++){
nums[str.indexOf(c[j])] +=1;
}
}
for(int i=0;i<nums.length-1;i++){
System.out.print(nums[i]+" ");
}
System.out.println(nums[9]);
}
}
}
#include<iostream>
using namespace std;
int count(int n, int x) {
int res = 0, j;
for (int i = 1; j = n / i; i *= 10) {
int high = j / 10;
if (x == 0) {
if (high)
high--;
else
break;
}
res += high * i;
int tem = j % 10;
if (tem > x)
res += i;
else if (tem == x)
res += n - j * i + 1;
}
return res;
}
int main(){
int n;
while (cin >> n){
cout << count(n, 0);
for (int i = 1; i <= 9; i++)
cout << " " << count(n, i);
}
return 0;
}
//最优的解法了,时间复杂度O(log10(N)),以10为底N的对数,也就是N的位数
2位数的情况: N=13,个位数出现的1的次数为2,分别为1和11,十位数出现1的次数为4,分别为10,11,12,13,所以f(N) = 2+4。 N=23,个位数出现的1的次数为3,分别为1,11,21,十位数出现1的次数为10,分别为10~19,f(N)=3+10。 由此我们发现,个位数出现1的次数不仅和个位数有关,和十位数也有关,如果个位数大于等于1,则个位数出现1的次数为十位数的数字加1;如果个位数为0,个位数出现1的次数等于十位数数字。而十位数上出现1的次数也不仅和十位数相关,也和个位数相关:如果十位数字等于1,则十位数上出现1的次数为个位数的数字加1,假如十位数大于1,则十位数上出现1的次数为10。 3位数的情况: N=123 个位出现1的个数为13:1,11,21,…,91,101,111,121 十位出现1的个数为20:10~19,110~119 百位出现1的个数为24:100~123 我们可以继续分析4位数,5位数,推导出下面一般情况: 假设N,我们要计算百位上出现1的次数,将由三部分决定:百位上的数字,百位以上的数字,百位一下的数字。 如果百位上的数字为0,则百位上出现1的次数仅由更高位决定,比如12013,百位出现1的情况为100~199,1100~1199,2100~2199,…,11100~11199,共1200个。等于更高位数字乘以当前位数,即12 * 100。 如果百位上的数字大于1,则百位上出现1的次数仅由更高位决定,比如12213,百位出现1的情况为100~199,1100~1199,2100~2199,…,11100~11199,12100~12199共1300个。等于更高位数字加1乘以当前位数,即(12 + 1)*100。
如果百位上的数字为1,则百位上出现1的次数不仅受更高位影响,还受低位影响。例如12113,受高位影响出现1的情况:100~199,1100~1199,2100~2199,…,11100~11199,共1200个,但它还受低位影响,出现1的情况是12100~12113,共14个,等于低位数字13+1。
public static long getFactorCount(long num,byte factor){
long count=0;
long current=0,next=0,before=0;
long i=1;
while((num/i)!=0){
current=(num/i)%10;
next=num/(i*10);
before=num-(num/i)*i;
if(current<factor){
count+=next*i;
}
else if(current==factor){
count+=next*i+before+1;
}
else if(current>factor)count+=(next+1)*i;
i*=10;
}
return count;
}
def count_digit(n, x):
high = n // 10
cur = n % 10
low = 0
digit = 1
res = 0
while high != 0 or cur != 0:
if 0 <= cur < x:
res += high * digit
elif cur == x:
if x == 0:
res += (high - 1) * digit + low + 1
else:
res += high * digit + low + 1
elif cur > x:
if x == 0:
res += high * digit
else:
res += (high + 1) * digit
low += cur * digit
cur = high % 10
high //= 10
digit *= 10
return res
if __name__ == '__main__':
n = int(input())
for i in range(9):
print(count_digit(n, i), end=' ')
print(count_digit(n, 9), end='')
#include <iostream>
#include <algorithm>
#include<cmath>
using namespace std;
int main()
{
int a[10] = { 0,0,0,0,0,0,0,0,0,0 };
int num;
cin >> num;
for (int i = 0; i <= 9; i++)
{
int digit = 1;
int temp = 0;
while (num / digit != 0)
{
int qian = num / 10 / digit;
int cur = (num / digit) % 10;
int hou = num % digit;
if (cur > i)
{
if (i != 0)
temp += (qian + 1) * digit;
else temp += qian * digit;
}
else if (cur == i)
{
if (i != 0)
temp += qian * digit + hou + 1;
else temp += (qian - 1) * digit + hou + 1;
}
else
{
temp += qian * digit;
}
digit *= 10;
}
a[i] = temp;
}
cout << a[0];
for (int i = 1; i <= 9; i++)
{
cout << ' ' << a[i];
}
} import java.util.*;
public class Main {
public static void main(String[] ags) {
Scanner in = new Scanner(System.in);
long n = in.nextLong();
in.close();
long[] numbers = new long[11];
long i =0;
for( i=1; n/i!=0;i=i*10) {
for(int j=1; j<10;j++) {
/**
*(n%(i*10))/i 是计算当前位置上的数,看前面同学的算法,分别计算before,current,after似乎更容易
*/
if(j<((n%(i*10))/i)) {
numbers[j]=numbers[j]+(n/(i*10) + 1)*i;
}
else if(j==((n%(i*10))/i)) {
numbers[j]=numbers[j]+(n/(i*10))*i+n%i+1;
}
else numbers[j]=numbers[j]+(n/(i*10))*i;;
}
if(((n%(i*10))/i)==0) {
numbers[0]=numbers[0]+(n/(i*10)-1)*i+n%i+1;
}
else {
numbers[0]=numbers[0]+(n/(i*10))*i;
}
}
for(int j =0; j<9; j++) {
System.out.print(numbers[j] + " ");
}
System.out.print(numbers[9]);
}
}
就这么个题,从早上写到晚上,脑子里像一团浆糊
import java.util.Scanner;
/*
* 本文内容主要参考:https://blog.csdn.net/zjkc050818/article/details/66474150
* 关键之处在于针对不同的位置分别统计可能出现的的次数,然后汇总返回
* */
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
int[] count = new int[10];
help(count, n);
System.out.print(count[0]);
for (int i = 1; i < 10; i++) {
System.out.print(" " + count[i]);
}
System.out.println();
}
}
private static void help(int[] count, int n) {
for (int i = 1; n / i >= 1; i *= 10) {
int before = n / (i * 10);
int current = n % (i * 10) / i;
int after = n % i;
// 针对0进行特殊处理
if (current == 0) {
count[0] += (before - 1) * i + after + 1;
} else {
count[0] += before * i;
}
// 对于1-9的元素进行统计
for (int j = 1; j < 10; j++) {
if (j < current) {
// 对于0这种情况需要增加1处理
count[j] += (1 + before) * i;
} else if (j == current) {
count[j] += before * i + after + 1;
} else {
count[j] += before * i;
}
}
}
}
}
/*
思路:对整数n进行取位运算(自己瞎起的名字,意思是取出个位、十位...)
比较当前位和需要统计的数字,寻找规律如下:
(i表示当前的位数,i=10表示比较十位数字;
next表示当前位的后几位数字,before表示当前位的前几位数字
例如:n=123456,i=100,则当前位为百位数字4,next表示123,before表示56)
当统计数字为0时:
1> 当前位==0: count += (next - 1) * i + num % i +1;
2> 当前位!=0: count += next * i;
当统计数字不为0时:
1> 当前位 > 统计数字: count += (next+1)*i;
2> 当前位 = 统计数字: count += next*i + before + 1;
3> 当前位 < 统计数字: count += next*i;
*/
//代码如下:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long n = scanner.nextLong();
for (byte i = 0; i < 10; i++) {
System.out.print(getCount(n, i));
if (i != 9) {
System.out.print(" ");
}
}
scanner.close();
}
private static long getCount(long num, byte factor) {
long count = 0;
long current = 0, next = 0, before = 0;
long i = 1;
while ((num / i) != 0) {
current = (num / i) % 10;// 取出第几位的数字
next = num / (i * 10);// 得到current的高位数字
before = num - (num / i) * i;// 得到current的低位数字
// 比较current和factor的大小
if (factor != 0) {
if (current > factor)
count += (next + 1) * i;
else if (current == factor)
count += next * i + before + 1;
else if (current < factor)
count += next * i;
} else if (factor == 0) {
if ((num / i) % 10 == factor)
count += (next - 1) * i + num % i + 1;
else
count += next * i;
}
i *= 10;
}
return count;
}
}
/**
* 时间复杂度是O(n x log10(n))
* */
public static int[] countOfNumber(int number) {
int[] resultArray = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if (number < 1) {
return resultArray;
}
for (int i = 1; i < number + 1; i++) {
String iString = String.valueOf(i);
for (int j = 0; j < iString.length(); j++) {
String jString = iString.substring(j, j + 1);
int key = Integer.parseInt(jString);
int value = resultArray[key];
resultArray[key] = value + 1;
}
}
return resultArray;
}
import string def count(number, c_list): next_number = number -1 if 1 == number: c_list[1] += 1 return while 0 != number: c_list[number%10] += 1 number = number/10 count(next_number, c_list) if __name__ == '__main__': input_num = string.atoi(raw_input()) c_list = [0,0,0,0,0,0,0,0,0,0] count(input_num, c_list) print ' '.join([str(a) for a in c_list])
#include <iostream>
using namespace std;
int digitCount(long num, short digit) {
int i = 1, count = 0;
while (num / i > 0) {
long before = num / (i * 10);
if (digit == 0) { //对于0要特殊处理
before--;
}
long after = num - num / i * i;
short current = num / i % 10;
if (current == digit) {
count += before * i + after + 1;
} else if (current > digit) {
count += (before + 1) * i;
} else if (current < digit) {
count += before * i;
}
i *= 10;
}
return count;
}
int main(int argc, const char * argv[]) {
long num;
cin >> num;
for (int i = 0; i < 10; i++) {
int k = digitCount(num, i);
cout << k;
if (i != 9) {
cout << ' ';
}
}
return 0;
}
不确定有没有bug, 例子上的输出通过。有点儿动态规划的意思, 每遇到一个数字,把每一位提取出来,累加到该数字之前的结果上。 看了其他人的回答,测试 900000000,输出为 708888897 820000000 820000000 820000000 820000000 820000000 820000000 820000000 820000000 720000001
public static void calculate(int n) {
int[] numbers = new int[10]; for (int i = 1; i<=n; i++) {
int k = i; do {
numbers[k % 10]++; k /= 10;
} while (k > 0);
}
for (int number : numbers) {
System.out.println(number + " "); }
}