| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1920 人关注过本帖, 1 人收藏
标题:一道acm的题,提交TE,求大侠讲解一下解题思路(已附上自己思路和代码)
只看楼主 加入收藏
zhu224039
Rank: 8Rank: 8
等 级:贵宾
威 望:17
帖 子:862
专家分:792
注 册:2012-7-29
收藏
得分:0 
可以把数 进行分解 假如为数为N >=10  m= N/1 =m/2 ....... 逐一进行分解,分解成 用 1 2 3 4 5 6 7 8 9  10 进行相乘的数  
比如 120  120/1=120  120/2=60   60/3=20 20/4=5 5/5 =1  120=1*2*3*4*5  剥离次数乘以2就是因子数
这里面好像要注意   3 6  2 4 8   2 10  具体的还不是很清楚

在进行玻璃的过程中 如果出现一个商  扫描了 1到10 的数字都不能整除他  就剥离结束  剥离出来的因子个数就是剥离次数x2+1

那么 对于有N个因子的数  就得对数进行 N次剥离  找出这个最小的N 就可以了。
那么最小的数  肯定是 1->2->3->4->5->6->7->8->9->10  这个称谓一次整剥离  到底包不包括10 的剥离 请大家考究
如果还能继续剥离的话 从1接着来剥 2->3->4->5->6->7->8->9->10 这称为二次整剥离
不整的剥离就是 1 2  3 4 5 6 不到10 的剥离 这个就是不整的


从上面的120的演示 我们看出  剥离是 1*120  60*2  
这证明  1 2 3 4 5 6 7 8 9 10
最后一趟剥离 这个陈数当然越小越好 就让他为1把  那么N个因子就 最理想的是  最后的前一次剥离是  
剥离过程  还需要考究   怎么选择 现在我还不清楚,想了半个晚上  就想出了这么点头绪

当然这个剥离 你得用 % 求余来判定  剥离条件是否满足   才能进行求商运算
不满足剥离条件且需要推出剥离函数时  计数 不满足剥离情况的  i 值是为 10 的 或者 是发觉最后商为1 或者0  也要推出剥离了


具体怎么剥  才是剥的 最小的数  我还不大清楚  不可能这么简单的剥把

[ 本帖最后由 zhu224039 于 2012-8-30 09:00 编辑 ]

我要成为嘿嘿的黑客,替天行道
2012-08-30 08:44
zhu224039
Rank: 8Rank: 8
等 级:贵宾
威 望:17
帖 子:862
专家分:792
注 册:2012-7-29
收藏
得分:0 
可控的是 数的平方次增长  跨度很大

我要成为嘿嘿的黑客,替天行道
2012-08-30 08:47
zhu224039
Rank: 8Rank: 8
等 级:贵宾
威 望:17
帖 子:862
专家分:792
注 册:2012-7-29
收藏
得分:0 
可控的是 数的平方次增长  跨度很大  肯定不是所需要的数

另外一种缩小搜索范围的构思 发觉可控性很差
1.除法组成部分 除数 被除数 商 余
有效因子数可能出现的范围   设X 为除数 Y 我被除数 A 为S商 B为余

2.那么初步判定可以得出一个结论   1是特列不在此结论内讨论
B=X/Y=1 的Y 除去 X=Y外 一律不可能是因子  因为商为1了 就代表余数B 是不可能大于Y的,也就是除出来就是1.多少
这里给出了一个信息 也就是  Y*2<=X  这样就缩小了因子取数的范围
算法第一步就出来了  找出Y*2<=X 的Y值   x/2 可找到 这个数Y  如果是偶数那么Y=X/2+1  奇数的话  Y=X/2+1
比如 56 56/2=28  那么29 30  31 32  33  34 35 比如57/2=28.5 29 30 31 32...................
都是不能成为因子的
初步就求出了 Y可能是因子的范围     1<Y<X/2  
2.  现在就可以将数据从中间切开了   X/4
为什么这么做呢?   2  3  4  5 .......  X/4  ................X/2+1
现在就可以看到  2 与 X/2位置上的对应  3 与 X/3的  位置上的数据对应  依次内推  在 就会发现一个有一个很有趣的问题
这样一直让  X除以集合{ X/4 } 内的数据  通过这种方式来求数据的对应位置的时候  当能取  1  2  3  4 对应位上的数  超过4就找不到可能因子了,为什么呢
因为取到 5 的时候  他的对应为要为X/5   你看看是不是小于 X/4了  也就是  X/4 只能取  4个对称位上的数也就是 8个因子可能,  可能是 因子  这个说明 X/4 到 X/2 之间 只 可能有4个相对应因子存在的可能性 也就是8个
为什么要这么分呢 因为对称直观 而且利于分析嘛    你也可以取  X/5 或者其他的  就像希尔排序一样  你自己选择增量  此时这个数应该最起码大于  32  才可能有8因子可能    也就是说此情况最多有 8因子

3.看看 X/8的可能性,现在已经判定了  X/4到 X/2 区间的因子数可能性了,  我们就可以把范围再缩小下   这个范围有上 可得    在 5到X/4 之间了
    可以取数的就是  5 6  7  8 了      对应区间 也是 8个因子可能    也就是  X/8 到 X/4区间内 就只有4个因子  另4个因子就是5 6 7 8  共计8个
这样是不可能限制的分下去的   当然  8<X/4
那么这个分量终止在哪呢    已 56  为例子   56/2=28    56/4=14  56/8=7  56/16=3 56/32=1  56/64=0  
                                          64/2=32    64/4=16   64/8=8 64/16=4 64/32=2  64/64=1 了  且数的取值 范围为 这个主要看最后的一次求余的余数而定  恰好不用算最后一次 和 恰好是 1  比如  意思就是 32/2  16/4 后面的一次求余是0/8  和 64/2 32/4 8/8 这两种情况可以框定数的范围了 范围就是 32<=X<=64 这个怎么算过来的呢 28 是56/2 的余数 7是28/4的余数 看到没 2 4 8 16 就是他们的商数 自己用除法弄下肯定能明白的,为什么要把商相乘 最大可能因子是 8  因为他x/2 的值只除了1个2    (猜想: 最后的   N/M=0了的时候  M-N的值每小1个数 减去2个可能因子 每少一个 减去2个因子)  拿64说事  就是 1 2 4 8 16 32 64   按照算法8是被多算了1次的 呵呵 8*8 是64  所以因子数 最大是 7   每多除一次2  增量算法是8 ,实际取数的时候取7  肯定会是这样的 因为都是4的倍

好了 锁定数 我觉得推理对于没计算器 实在是麻烦的很 直接写算法了  对不对 再说
根据上面的推论 我们了解了数的动向,现在开始逆向求解
写出递推公式

11=10*1+1  10 1  1  都是可以的

对于n  n/2 让我们知道要给出几个对应位出来  假设 X 的因子数 是n   那么 X/2 每除以 2  就会给出4个位   上面有推论哟 X=16 给出的对应位是4 X=32  给出的是8 依次为是在次基础上*2
归纳出来就是公式 假设要给出因子对应位为 N  a=N/2   那么有  数NUM 满足此要求  则有  NUM/2的(a+1)方 =0  和 0

我要成为嘿嘿的黑客,替天行道
2012-08-30 08:48
zhu224039
Rank: 8Rank: 8
等 级:贵宾
威 望:17
帖 子:862
专家分:792
注 册:2012-7-29
收藏
得分:0 
  睡觉  最近怎么这么 恶心  到处都是数学  到处都是 数学

我要成为嘿嘿的黑客,替天行道
2012-08-30 08:54
zhu224039
Rank: 8Rank: 8
等 级:贵宾
威 望:17
帖 子:862
专家分:792
注 册:2012-7-29
收藏
得分:0 
想了那么久  怎么感觉是在逆运算乘法呢

我要成为嘿嘿的黑客,替天行道
2012-08-30 08:57
netlin
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:24
帖 子:544
专家分:4308
注 册:2012-4-9
收藏
得分:0 
有趣,多用用脑总是好的!

做自己喜欢的事!
2012-08-30 11:41
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
呵呵,算法的分析也只能到这儿了,pangding的补充已经很详细明了。

至于代码的构造方式属于编程的基础技巧,展开来用文字叙述篇幅会很长,不如直接看代码来的明了。

刚刚试了一下,4ms AC(所有题目的AC时间似乎没有低于4ms的,包括a + b problem)。

我的本意是想让大家自己想想写一下,这种东西就像玩游戏一样,总是自己亲手通关比较有趣。

我不想破坏大家思考的乐趣。但是如果大家已经不想再琢磨了,说一声我放代码。

重剑无锋,大巧不工
2012-08-30 11:54
netlin
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:24
帖 子:544
专家分:4308
注 册:2012-4-9
收藏
得分:0 
以下是引用pangding在2012-8-28 22:24:26的发言:

杨大哥已经提醒的差不多了。我详细说说我的思路,应该和杨大哥想的一样。

任何一个数最终能分解成:p1^r1 * p2^r2 ... ps^rs 的形式,其中 pi 都是素数,且这种分解形式是唯一的(这个结论就是杨大哥说的算术的基本定理)。这个过程称为素因数分解。比如 36 = 2^2 * 3^2。
那么 36 的全部约数能从这个形式中求出。2 这个因数能用 0次,1次,2次,3这个因数也能用0次,1次,2次,搭配起来能凑出 3*3 = 9 个组合,都是 36 的约数。比如 2 用 0 次配 3 用 0 次,就是 2^0 * 3^0 = 1。是 36 的一个约数。
一般地,对于任何数的分解形式:p1^r1 * p2^r2 ... ps^rs 一共就有 (r1+1)(r2+1)...(rs+1) 个约数。

现在反这想这个问题,如果我想要一个有 9 个因数的数,那么我需要一个式子 (r1+1)(r2+1)...(rs+1) = 9 才行。
杨大哥给了个结论,是如果 n 是质数的话,它就不可能能分解成几个数的乘积于是只能是 r1+1 = n,任意质数 p^(n-1) 都满足只有 n 个约数的条件,当然为了尽量小,要取 p = 2。
对于 9 的话,可以是 8+1 = 9, (2+1)(2+1) = 9,所以即可能是 2^8,也可以是 2^2 * 3^2。这里得找个小的。因为 2^8 可以看成 2^2 * 2^6, 所以这里就是要决断 2^6 和 3^2 谁大的问题。

这里我还没有太想好代码应该怎样处理。主要是判断如何拆分这个 n,以使得最后得的乘积尽量小。不过思路肯定是这样下去的。
很精彩!

做自己喜欢的事!
2012-08-30 12:06
justNPC
Rank: 5Rank: 5
等 级:职业侠客
帖 子:101
专家分:311
注 册:2012-8-11
收藏
得分:0 
求杨大哥代码一阅,关于怎样组合因数,求得最小值这一步的处理没啥头绪啊
2012-08-30 21:43
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
这两天很忙,先发代码,有疑问以后解释。

程序代码:
#include<stdio.h> 
#include<math.h> 

#define LEN 10 

int p[LEN] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; 
double e[LEN];

int mr[LEN], tr[LEN], rn; 
double min;

void f(int a, int r, int d, double v) 
{ 
    int i; 
    double tv; 
    if(v > min) return; 
    if(a == 1) 
    {
        if(v < min) 
        { 
            for(i = 0; i < d; i++) mr[i] = tr[i]; 
            rn = d; 
            min = v; 
        } 
        return; 
    } 
    for(i = a < r ? a : r; i > 1; i--) 
    { 
        if(a % i) continue; 
        tr[d] = i - 1; 
        tv = tr[d] * e[d]; 
        f(a / i, i, d + 1, v + tv); 
    } 
}

long long cal(int a) 
{ 
    int i; 
    long long m; 
    min = a; 
    f(a, a, 0, 0); 
    for(m = 1, i = 0; i < rn; i++) 
        while(mr[i]--) m *= p[i]; 
    return m; 
}

int main() 
{ 
    int i; 
    for(i = 0; i < LEN; i++) e[i] = log(p[i]); 
    while(scanf("%d", &i) != EOF) printf("%lld\n", cal(i)); 
    return 0; 
}

重剑无锋,大巧不工
2012-08-31 21:32
快速回复:一道acm的题,提交TE,求大侠讲解一下解题思路(已附上自己思路和代码 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017141 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved