2015华为机试——整数分割

题目描述:

一个整数可以拆分为2的幂的和,例如:

7 = 1+ 2 +
4

7 = 1 + 2
+ 2 + 2

7 = 1 + 1
+ 1 + 4

7 = 1 + 1
+ 1 + 2 + 2

7 = 1 + 1
+ 1 + 1 + 1 + 2

7 = 1 + 1
+ 1 + 1 + 1 + 1 + 1

总共有六种不同的拆分方式

再比如: 4可以拆分成:
4 = 4, 4 = 1+1+1+1, 4 = 2+2, 4 = 1+1+2.

用f(n)表示n的不同拆分的种数,例如f(7)
= 6.

要求读入n(不超过1000000),输出f(n)
% 1000000000。

解题思路:

对于奇数 n = 2k+1, 它的拆分的第一项一定是1, 考虑去掉这个1,其实就一一对应于2k的拆分,因此f(2k+1)
= f(2k)。

对于偶数n = 2k: 考虑有1和没有1的拆分。有1的拆分,与(2k-1)的拆分一一对应,与上面奇数的情况理由相同:没有1的拆分,将每项除以2,正好一一对应于k的所有拆分,因此f(2k) = f(2k-1) + f(k)。

最终结果只要求除以十亿的余数,在int的表示范围内,因此也不需要大数运算。注意余数的性质:(a+b)%m = (a%m+b%m)%m,所以只要对每个中间结果也都取余数,就不会有溢出问题,且不会改变最终输出结果。

代码如下:

	public static void main(String[] args)
	{
		Scanner sc=new Scanner(System.in);
		while (sc.hasNext())
		{
			int input=sc.nextInt();
			FenGe(input);
		}
		sc.close();
	}

	public static void FenGe(int n)
	{
		List<Integer> list=new ArrayList<Integer>();
		list.add(0);
		if ((n>=1)&&(n<=1000000))
		{
			for (int i = 1; i <= n; i++)
			{
				if (i%2==1)
				{
					if (i==1)
					{
						list.add(1);
					}
					else
					{
						list.add(list.get(i-1));
					}
				}

				if (i%2==0)
				{
					list.add((list.get(i-1)+list.get(i/2))%100000000);
				}
			}
			System.out.println(list.get(n));
		}
		else
		{
			System.out.println(-1);
		}
	}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 00:58:08

2015华为机试——整数分割的相关文章

2015华为机试——计算整数的位数

题目描述: 输入一个五位以内(包括5位)的正整数,(1)判断它是一个几位数:(2)逆序输出其各位数字. 输入:多组数据,每组一行 输出:对应一行输出 样例输入:56439 样例输出:5 93465 解题思路:使用StringBuffer的reverse方法即可. 代码如下: public static void main(String[] args) { Scanner sc=new Scanner(System.in); while (sc.hasNext()) { String input=

华为机试—整数相除

两个整数相除,将结果用字符串返回.如果是循环小数,将循环的位用括号括起来. 函数原型为 void div(const int a,const int b,char *str) 输入:1 3 输出:0.(3) #include<iostream> #include<string> using namespace std; int maxn = 100; //设置字符串的最大位数 int reminder_exist[10000]; int reminder_pos[10000]; v

华为机试—整数数组排序(字符串输入输出)

#include<stdio.h> /* 编写一个程序,实现排序算法,用户输入证书序列,程序将所有证书从小到大排序并输出 输入:数字序列,长度小于1024,两个数字之间以逗号分隔,所有数字均为非负整数,整数个数小于128 输出:排序后的整数序列,两个数字之间以逗号分隔 */ int main(int argc, char *argv[]) { int a[129]; int i=0; scanf("%d",&a[i++]); char c; while(scanf(

2015华为机试——计算两个正整数的最大公约数和最小公倍数

题目描述: 接口说明 原型: long getMaxDivisor(long lFirstInput, long lSecondInput); 输入参数: int first: 第一个整数; int second: 第二个整数; 返回值: 最大公约数 long getMinMultiple(long lFirstInput, long lSecondInput); 输入参数: int first: 第一个整数; int second: 第二个整数; 返回值: 最小公倍数 解题思路:使用辗转相除法

2015华为机试——尼科彻斯定理

题目描述: 验证尼科彻斯定理,即:任何一个整数m的立方都可以写成m个连续奇数之和.m属于[1,100],超出范围则报错. 例如: 1^3=1 2^3=3+5 3^3=7+9+11 4^3=13+15+17+19 解题思路:不难发现展开式从(n*n - n + 1)开始,步进2显示,共显示n个数. 代码如下: public static void main(String[] args) { Scanner sc=new Scanner(System.in); while (sc.hasNext()

2015华为机试—— 整型数排序

要求:请实现对一整型数序列的排序操作. 需求: 1.对输入的整型数序列A,完成升序排列,将结果序列从B中输出.以整数值大小为关键字排序,即小数在前,大数在后. 2.当序列中存在多个同样大小的数时,输出序列中仅保留一个. 举例: 输入序列A:76,92,34,34,59,16,59,45 符合要求的输出序列B:16,34,45,59,76,92 约束: 1.输入的序列至少含有一个整型数,否则应该返回null: 2.输入序列中的整数值使用int类型: 接口说明 /******************

2015华为机试

第一题(60分): 按要求分解字符串,输入两个数M,N:M代表输入的M串字符串,N代表输出的每串字符串的位数,不够补0.例如:输入2,8, "abc" ,"123456789",则输出为"abc00000","12345678","90000000" #include<iostream> using namespace std; void solve(char *str , int n , in

2015华为机试——合唱队

描述: 计算最少出列多少位同学,使得剩下的同学排成合唱队形 说明: N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2-,K,他们的身高分别为T1,T2,-,TK,   则他们的身高满足存在i(1<=i<=K)使得Ti<T2<......<Ti-1<Ti>Ti+1>......>TK. 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可

2015华为机试——最大公约数

描述: 输入2个数字,最后输出2个数字的最大公约数 题目类别: 位运算 难度: 初级 运行时间限制: 无限制 内存限制: 无限制 阶段: 入职前练习 输入: 2个整数 输出: 输出数字1和2的最大公约数 样例输入: 2 3 样例输出: 1 代码如下: public class gongyueshu { public static void main(String[] args) { Scanner sc=new Scanner(System.in); while (sc.hasNext()) {