package org.shaoxinglay.algorithm;
import java.math.BigInteger;
/**
* 问题:有一个整数n,写一个函数f(n),返回0到n之间出现的"1"的个数。 比如f(13)=6,现在f(1)=1,问此后最大的f(n)=n的n是什么?<br/>
* 本类提供3种不同实现算f(n)的方法,理论上能处理趋于无穷大的整数,只要计算机内存足够大,而不限于Java的整型、长整型。
*
*/
public class Demo {
/**
* 基于字符串实现的算f(n),原理最通俗易懂,但同时效率较为低下。不宜处理大数。
*
* @param n
* 自变量n的值
* @param target
* 目标数字(0 <= target < 10)
* @return f(n)的值
*/
public static int execByString(int n, int target) {
checkTarget(target);
int count = 0;
char targ = (target + "").charAt(0);
String s = null;
for (int i = 0; i <= n; i++) {
s = "" + i;
for (int j = 0; j < s.length(); j++) {
if (s.charAt(j) == targ) {
count++;
}
}
}
return count;
}
/**
* 与使用字符串处理一样,使用迭代的方式进行处理,时间复杂度可认为是O(n·log<sub>10</sub>n)。<br />
* 欲求f(n),必要先求f(n-1),因此效率其实不高,处理大数也是力不从心啊。
*
* @param n
* 自变量n的值
* @param target
* 目标数字(0 <= target < 10)
* @return f(n)的值
*/
public static long execByIterate(int n, int target) {
checkTarget(target);
long count;
int num, temp;
count = num = temp = 0;
while (num <= n) {
temp = num;
while (temp != 0) {
if (temp % 10 == target)
count++;
temp /= 10;
}
num++;
}
if (target == 0) {
count++; // 把初始的0补上
}
return count;
}
/**
* 使用排列组合的方式进行处理,能把时间复杂度降到O(log<sub>10</sub>n),因此,本方法处理Long.MAX_VALUE也毫无鸭梨!
*
* @param n
* 自变量n的值
* @param target
* 目标数字(0 <= target < 10)
* @return BigInteger表示的f(n)
*/
public static BigInteger execByPermutation(long n, int target) {
checkTarget(target);
int[] nums = getArray(n);
int len = nums.length;
BigInteger count = new BigInteger("0");
BigInteger powbase = new BigInteger("10");
long left, right;
for (int i = 0; i < len; i++) {
right = (long) Math.pow(10, (len - i - 1));
if (target != 0) {
left = (long) (n / Math.pow(10, len - i));
if (nums[i] > (target - 1)) {
left++;
}
} else {
left = (long) (n / Math.pow(10, len - i));
if (left > 0) {
left = left - (long) Math.pow(10, i - 1) + 1;
}
}
count = count.add(BigInteger.valueOf(right * left));
if (nums[i] == target) {
long temp = (long) Math.pow(10, (len - i - 1));
long sub = temp - ((long) (n % temp)) - 1;
count = count.subtract(BigInteger.valueOf(sub));
}
}
if (target == 0) {
count = zeroCompensate(len, count, powbase);
}
return count;
}
/**
* 使用排列组合的方式进行处理,能把时间复杂度降到O(log<sub>10</sub>n),因此,本方法处理再大的数也无鸭梨!
*
* @param n
* String类型,一个整数的字符串表示,例如:5236521452145 表示为"5236521452145" <br>
* 注意:只能是十进制的表示法
* @param target
* 目标数字(0 <= target < 10)
* @return BigInteger表示的f(n)
*/
public static BigInteger execByPermutation(String n, int target) {
checkTarget(target);
BigInteger src = new BigInteger(n);
String nstr = src.toString();
int[] nums = new int[nstr.length()];
for (int i = 0; i < nums.length; i++) {
nums[i] = Integer.parseInt(nstr.charAt(i) + "");
}
int len = nums.length;
BigInteger count = BigInteger.ZERO;
BigInteger powbase = BigInteger.TEN;
BigInteger left = BigInteger.ZERO;
BigInteger right = BigInteger.ZERO;
for (int i = 0; i < len; i++) {
right = powbase.pow(len - i - 1);
if (target != 0) {
left = src.divide(powbase.pow(len - i));
if (nums[i] > (target - 1)) {
left = left.add(BigInteger.ONE);
}
} else {
left = src.divide(powbase.pow(len - i));
if (i > 0) {
left = left.subtract(powbase.pow(i - 1))
.add(BigInteger.ONE);
}
}
count = count.add(right.multiply(left));
if (nums[i] == target) {
BigInteger temp = powbase.pow(len - i - 1);
BigInteger sub = temp.subtract(src.mod(temp)).subtract(
BigInteger.ONE);
count = count.subtract(sub);
}
}
if (target == 0) {
count = zeroCompensate(len, count, powbase);
}
return count;
}
private static BigInteger zeroCompensate(int len, BigInteger count,
BigInteger powbase) {
int bl = len - 2;
if (bl < 1) {
count = count.add(BigInteger.valueOf(1));
} else if (bl == 1) {
count = count.add(BigInteger.valueOf(10));
} else {
BigInteger bigI = BigInteger.valueOf(0);
for (int i = 1; i < bl; i++) {
bigI = bigI.add(powbase.pow(i));
}
BigInteger bc = BigInteger.valueOf(bl).multiply(powbase.pow(bl))
.subtract(bigI);
count = count.add(bc);
}
return count;
}
/**
* 如果目标数字没在0-9中抛出非法参数异常
*
* @param target
* 目标数字
* @throws IllegalArgumentException
*/
private static void checkTarget(int target) throws IllegalArgumentException {
if (target < 0 || target > 9) {
throw new IllegalArgumentException("目标数字" + target + "不在0 - 9中");
}
}
private final static long[] sizeTable = { 9, 99, 999, 9999, 99999, 999999,
9999999, 99999999, 999999999, 9999999999L, 99999999999L,
999999999999L, 9999999999999L, 99999999999999L, 999999999999999L,
9999999999999999L, 99999999999999999L, 999999999999999999L,
Long.MAX_VALUE };
private static int sizeOfLong(long x) {
for (int i = 0;; i++)
if (x <= sizeTable[i])
return i + 1;
}
private static int[] getArray(long n) {
int len = sizeOfLong(n);
int[] result = new int[len];
int i = len - 1;
while (i >= 0) {
result[i--] = (int) (n % 10);
n = n / 10;
}
return result;
}
}
对于f(n)=n,最大的n值是多少,可证明n是确定的,原理是当n大于某一数值时,f(n)恒大于n。
分享到:
相关推荐
有一个整数n,写一个函数f(n),返回0到n之间出现的 "1 "的个数。比如f(13)=6,现在f(1)=1,问下一个最大的f(n)=n的n是什么?
在本题目中,我们需要编写一个C语言程序,用于计算从1到给定正整数N之间所有整数中数字"1"出现的总次数。这是一个典型的字符串处理和数学计算问题,涉及到了数字转换、字符串遍历以及计数算法。下面我们将深入探讨这...
这是因为如果n有一个大于其平方根的因数a,那么必然存在一个小于或等于其平方根的因数b,使得a * b = n。所以,我们只需要检查小于或等于√n的数即可,这大大减少了计算量。 下面是一个简单的C语言函数,用于判断一...
在这个编程任务中,我们需要在C语言环境下实现一个程序,该程序能从用户那里接收两个整数,然后在它们之间找出所有的素数,并显示出来。素数是大于1且只有1和其本身两个正因数的自然数。这里,我们不仅需要实现基本...
- **主函数**:`main()`函数首先定义了一个整数变量`nData`并赋值为300,然后分别调用`GetSum()`函数计算0和1的个数,并打印结果。 - **函数调用**:通过传入不同的参数`bZeroOrOne`,可以灵活地选择计算0或1的个数...
C语言程序设计-编写函数判断一个整数能否同时被3和5整除,若能则返回值为1,否则为0;调用该函数求出15~300之间能同时被3和5整除的数的个数;.c
在这个特定的示例中,“LabView 计算整数N内所有的素数”指的是利用LabView来编写一个程序,该程序能够找出从1到一个指定整数N之间所有素数。 素数是大于1且除了1和它自身以外没有其他正因数的自然数。判断一个数...
该函数`Factorial`接收一个整数`nNumber`作为参数,返回该整数阶乘末尾0的数量。它通过一个简单的循环不断地将`nNumber`除以5,并累加结果,直至`nNumber`小于5为止。 ##### 函数BigFactorial() 此函数用于处理大数...
标题中的“输入一个自然数n,求 ,同时统计结果中有多少个0。”是一个关于计算阶乘(Factorial)的问题,并且需要我们同时计算阶乘结果中0的数量。在这个问题中,"n!"代表n的阶乘,即1×2×3×...×n。 阶乘是数学...
C语言程序设计-编写main程序调用函数fact求解从m个元素选n个元素的组合数的个数;计算公式是: 组合数=m!(n!.(m-n)!);要求m不能小于n,否则应有容错处理;说明:函数fact(x)的功能是求x!;
在本题目中,我们需要使用C语言编写一个程序,该程序能接收用户输入的N个正整数,并统计其中奇数和偶数的数量。这是一道基础的编程练习,旨在帮助学习者掌握C语言的基本语法、循环结构以及条件判断。下面我们将详细...
结论是,不存在一个实系数多项式 \( f(x) \),能够满足题目中所描述的条件,即对于任意整数 \( a \) 和它在文本中的出现次数 \( b \),都有 \( f(a) = b \)。这是因为多项式函数的性质与文本中整数的计数特性不兼容...
C语言程序设计-计算从1开始到n的自然数中偶数的平方的和,n由键盘输入,并在main()函数中输出。(n是偶数).c
给定一个十进制正整数N,任务是从1开始到N的所有整数中统计数字“1”出现的总次数。例如,当N = 2时,只有数字1出现了一次;而当N = 12时,1分别出现在1、10、11和11中两次,因此总共出现了5次。 ### 解题思路与...
在编程领域,生成1到N的不重复随机数是一个常见的需求,这在各种场景中都有应用,例如模拟抽奖、创建随机测试数据或者在游戏中分配资源等。这个任务涉及到两个主要的知识点:随机数生成和数组去重。 首先,我们来...
当我们处理整数时,有时会遇到需要计算一个整数中包含"0"的个数的问题。这个任务通常在统计数字特性、字符串处理或者编码解码的场景中出现。本篇文章将详细讲解如何在不同的编程语言中判断并计算输入整数中"0"的个数...
在本项目中,我们主要探讨的是如何利用C++编程语言,结合Microsoft Foundation Classes (MFC)库来实现一个功能,即查找指定范围内(m到n)的前k个素数并将其输出。C++是一种静态类型、编译式、通用的、大小写敏感的...
这段代码首先定义了一个函数`countOnes`,它接受一个整数N并返回小于或等于N的所有整数中1的个数。然后在主函数`main`中,程序会从用户那里获取输入值N,并调用`countOnes`函数计算结果。 博客 "编程之美" 提到了这...
`main`函数是程序的入口点,首先获取用户输入的元素个数`n`,并检查其是否在1到10的范围内,然后初始化`list`数组,使其包含1到n的所有整数。 `getAllOrder`函数是核心的回溯函数,它接受两个参数,`begin`表示当前...
C语言程序设计-求大于lim(lim小于100的整数)并且小于100的所有素数并放在aa数组中,该函数返回所求出素数的个数