不懂算法之带分数
来源:互联网 发布:pageoffice php 编辑:程序博客网 时间:2024/05/22 17:00
题目描述
标题:带分数
100 可以表示为带分数的形式:100 = 3 + 69258 / 714
还可以表示为:100 = 82 + 3546 / 197
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。
题目要求:
从标准输入读入一个正整数N (N<1000*1000)
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
例如:
用户输入:
100
程序输出:
11
再例如:
用户输入:
105
程序输出:
6
资源约定:
峰值内存消耗 < 64M
CPU消耗 < 3000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
哎,说来也是惭愧,今天去参加校内蓝桥杯选拔赛,编程题最后一题就是这个,前面几道全是用穷举法做,这一道也很自然的想到用穷举法。但是粗略一想,我想先把这个带分数表达式先搞成字符串的形式,但是深入一想。。那尼玛是个无底洞,,果断放弃。之后观察第一个整数和分数的分子分母有什么关系么。。果然,没有,至少我看不出来。怪自己算法思想不够,数学功底欠缺,没有考虑分数的分子分母的位数在N(N<1000*1000&数字1~9分别出现且只出现一次)的条件下是有个上界的。
如果分母是一个五位数,那么分子也必须至少为五位数,因为如果分子不是五位数,那么这个分数一定是小于1的,那也就不可能是这个解了。既然分子分母都是五位数,又只有9个数字,那么分母不可能是五位数。所以这个分数分母的位数最多是4位,最少是1位。
对于第一个整数,由于N<1000*1000,至少存在如下关系不等式:
1 <= 这个整数的位数 <= N的位数;
如果这个整数的位数大于了N的位数,则肯定不是这一种可能了。
既然确定了整数和分母,分子其实可以通过反表示法来表示了:
a + b / c = n; ---> b = (n - a) * c;
设该等式形式为:
left + up / down = n;
核心代码:
for(down = 1; down < 10000; down++)
{
for(left = 1; left < Pow(10, n_bit); left++)
{
up = (n - left)*down;
if(Check(left, up, down))
{
count++;
printf("%ld + %ld / %ld\n", left, up, down);
}
}
}
解释:
外循环对分母从1到10000(分母是不会超过四位数的)循环,内循环对整数从1到10的n的位数次方(上面分析过整数的位数不会超过n的位数),那么整数和分母的值现在已经是确定了的,所以分子的值也是确定了。剩下的就只是判断这三个数1~9这九个数字是不是有且仅出现了一次即可,交给Check函数来做(如果满足要求,返回1,;否则返回0),如果满足了要求,那么计数变量count就自增1,然后输出这种情况下的表达式。
下面附上完整代码:
#include<stdio.h>int Num_Bit(long x);long Pow(int x, int y);int Check(long left, long up, long down);int main(void){int n;int count = 0;long up, left, down;int n_bit, up_bit, down_bit, left_bit;printf("Enter n: ");scanf("%d", &n);n_bit = Num_Bit(n);for(down = 1; down < 10000; down++){for(left = 1; left < Pow(10, n_bit); left++){up = (n - left)*down; if(Check(left, up, down)) { count++; printf("%ld + %ld / %ld\n", left, up, down); } }}printf("count: %d\n", count);return 0;}int Num_Bit(long x){int bit = 0;while(x){x = x/10;bit++;}return bit;}long Pow(int x, int y){int i;long z = 1;for(i = 1; i <= y; i++) z *= x; return z;}int Check(long left, long up, long down){int a[9] = {0};int t;while(left){t = left%10;if(t == 0) return 0;a[t-1]++;left = left/10;}while(up){t = up%10;if(t == 0) return 0;a[t-1]++;up = up/10;}while(down){t = down%10;if(t == 0) return 0;a[t-1]++;down = down/10;}for(t = 0; t < 9; t++){if(a[t]!= 1) return 0;}return 1;}
- 不懂算法之带分数
- 算法- 带分数(java)
- 密码与摘要算法---不懂之处
- 蓝桥杯之带分数
- 蓝桥杯之带分数
- 带分数
- 带分数
- 带分数
- 带分数
- 带分数
- 带分数
- 带分数
- 带分数
- 带分数
- 带分数
- 带分数
- 带分数
- 带分数
- Android实例demo20之自定义短信发送、第三方下载框架
- 利用Intent进行Activity之间的通信(2)
- 关于战舰STM32用PL2303下载线下载和BOOT的软件相关控制
- PHP词法解析源码分析之PHP标签、关键字、类、数字
- 词频分析(C#版)
- 不懂算法之带分数
- 使用C++方式解决CallFunc创建
- ubuntu12.04samba服务器配置
- 网页关键词频率计算(词频计算js版)
- 黑马程序员——java之JDK1.5新特性
- NDK编译的时候遇到No rule to make target needed by *.o
- 异常处理回调函数
- python程序的调试方法
- 多态与索引器