首页 > 学技术 > 技术网文 > C/C++ > 正文

[保留] 1 2 5三个数相加等于1000,共有多少种情况?要求行数


来源 chinaunix.net kuqin整理

1  2  5三个数相加等于1000,共有多少种情况?
要求行数。

写了一个三行的

 for(i=1;i<500;i++)
  for(j=1;j<200;j++)
    if((i*2+j*5)<1000)count++;

面试官说可以两行实现,请各位高手指点指点!



 langue 回复于:2007-03-23 22:36:38

.

for(i=1;i<500;i++) for(j=1;j<200;j++) if((i*2+j*5)<1000) count++;

这是一行的。

.


 cugb_cat 回复于:2007-03-23 22:45:41

引用:原帖由 langue 于 2007-3-23 22:36 发表
.

for(i=1;i<500;i++) for(j=1;j<200;j++) if((i*2+j*5)<1000) count++;

这是一行的。



哈哈,是这么回事~~~~
C代码都可以写在一行里的


 liuke432 回复于:2007-03-23 22:46:16

引用:原帖由 langue 于 2007-3-23 22:36 发表
.

for(i=1;i<500;i++) for(j=1;j<200;j++) if((i*2+j*5)<1000) count++;

这是一行的。




不是这个意思。  :)

好像可以再去掉一个for循环


 飞灰橙 回复于:2007-03-23 23:27:22

引用:原帖由 liuke432 于 2007-3-23 22:46 发表


不是这个意思。  :)

好像可以再去掉一个for循环 



for改while, 再去两个都没问题:mrgreen:


 liuke432 回复于:2007-03-24 00:28:48

不好意思,我没有表达明白意思。
我的意思其实是要求效率再高一点。


 ArXoR 回复于:2007-03-24 08:48:00


一般化一下, 设求的和为n
枚举5的个数就行了
设i个5, 则剩下的n - 5 * i 由2和1组成的种数为floor((n - 5 * i) / 2)
所求为
y = sigma{floor((n - 5 * i) / 2), 0 <= i <= floor(n / 2)}.
然后按i和n的奇偶性异同分类求和就可以得到close form了, 一个关于n的2次多项式.


[ 本帖最后由 ArXoR 于 2007-3-25 10:16 编辑 ]


 liuke432 回复于:2007-03-24 19:15:12

引用:原帖由 ArXoR 于 2007-3-24 08:48 发表
一般化一下, 设求的和为n
枚举5的个数就行了
设i个5, 则剩下的n - 5 * j 由2和1组成的种数为floor((n - 5 * j) / 2)
所求为
y = sigma{floor((n - 5 * j) / 2), 0 <= i <= floor(n / 2)}.
然后 ... 



恩 明白了   厉害!

这样就可以了


      for(i=1;i<200;i++)
         count+=(1000 - 5i)/2+1;



[ 本帖最后由 liuke432 于 2007-3-24 19:17 编辑 ]


 converse 回复于:2007-03-24 23:33:35

保留本帖,方便查找。


 liuke432 回复于:2007-03-25 07:26:07

感谢converse版主!    :)


 ArXoR 回复于:2007-03-25 10:24:40

引用:原帖由 converse 于 3/24/07 23:33 发表
保留本帖,方便查找。 




其实这个方法并不具有一般性, 因为集合{a_i}, 0 <= i < m, 中存在一个a_k, 使得 a_k | a_i, 0 <= i < m, 
这里a_k = 1.

一般的有限正整数集合的话, 生成函数才是王道...


 fengwy 回复于:2007-03-25 19:03:07

ArXoR 是学数学的?


 njmarshal 回复于:2007-03-26 02:14:07

for(i=1;i<200;i++)
    count+=(int)((1000-5*i-1)/2);



其实这里因为是 整数除法 所以强制转换 (int) 可以不要

[ 本帖最后由 njmarshal 于 2007-3-26 02:30 编辑 ]


 hake2000 回复于:2007-03-26 11:06:27

引用:原帖由 liuke432 于 2007-3-24 19:15 发表


恩 明白了   厉害!

这样就可以了


      for(i=1;i<200;i++)
         count+=(1000 - 5i)/2+1;

 



没注意边界值


 hake2000 回复于:2007-03-26 11:17:37

引用:原帖由 hake2000 于 2007-3-26 11:06 发表


没注意边界值 





for(k=1;k<200;k++)
{
    count2+=(1000 - 5*k -1)/2;
}


此时count2的结果为 0xc1c1




for(k=1;k<200;k++)
{
    count2+=(1000 - 5*k)/2;
}


此时count2的结果为 0xc224


百思不得其解,这两种情况结果应该相同亚。难道是我对除法运算还没弄明白???
郁闷


 hake2000 回复于:2007-03-26 11:19:39

引用:原帖由 hake2000 于 2007-3-26 11:17 发表




for(k=1;k<200;k++)
{
    count2+=(1000 - 5*k -1)/2;
}


此时count2的结果为 0xc1c1




for(k=1;k<200;k++)
{
    count2+=(1000 - 5*k)/2;
}


此 ... 



编译环境是gcc 3.2.2


 hake2000 回复于:2007-03-26 11:35:46

终于知道了,晕
低级失误亚!!! 一直以为 (1000 - 5*k)是奇数!!!!!!!!!!!!



 hake2000 回复于:2007-03-26 11:37:33

引用:原帖由 hake2000 于 2007-3-26 11:19 发表


编译环境是gcc 3.2.2 






for(k=1;k<200;k++)
{
    count2+=(1000 - 5*k)/2;
}




零个1的情况是不应该算的


 njmarshal 回复于:2007-03-26 13:09:34

引用:原帖由 liuke432 于 2007-3-23 22:29 发表
1  2  5三个数相加等于1000,共有多少种情况?
要求行数。

写了一个三行的

 for(i=1;i<500;i++)
  for(j=1;j<200;j++)
    if((i*2+j*5)<1000)count++;

面试官说可以两行实现,请各位高手指 ... 



从上面的代码可以看出题目的要求是"1" ,"2","5"分别至少要有 1 个

所以我们的代码可以这样写

// a c 可以为"2","5"任何一个
// b=1
// 原来的考虑有点欠缺
// 1 是很特殊的数字。任何正整数都可以用多个1相加得到
//  so  b must be 1
//                   ok?
//  但 a,b,c 不能相等
for(i = a ; i<1000 ; i+=a)  //i=a是保证至少有一个a
           count += (1000-i-b) /c;  //减去b是保证至少有一个b
                                 //除以c则反映出a,b组成1000-i的b,c合法组数




或者下面这样的代码也可以
但不如上面的好

// a,c=2,5 or a,c=5,2
b=1
for(i = 1 ; i<1000/a ; i++) 
        count += (1000 - i*a -b) /c;     


比如a=5  b=1 c=2就成了我上面的一个帖子代码
见13楼
引用:原帖由 njmarshal 于 2007-3-26 02:14 发表

for(i=1;i<200;i++)
    count+=(int)((1000-5*i-1)/2);



其实这里因为是 整数除法 所以强制转换 (int) 可以不要 



[ 本帖最后由 njmarshal 于 2007-3-26 17:40 编辑 ]


 ArXoR 回复于:2007-03-26 13:40:50

引用:原帖由 njmarshal 于 3/26/07 13:09 发表


从上面的代码可以看出题目的要求是"1" ,"2","5"分别至少要有 1 个

所以我们的代码可以这样写

// a b c 可以为"1","2","5"任何一个 ... 



不知道你在写什么, 我觉得你似乎没有明白为什么可以这样算.


 njmarshal 回复于:2007-03-26 16:55:34

引用:原帖由 ArXoR 于 2007-3-26 13:40 发表


不知道你在写什么, 我觉得你似乎没有明白为什么可以这样算. 


你觉得哪里不理解

我上面的代码用a b c代替了 5  2   1 
是这个程序具有扩展性 

可以完成任意3个正整数组合的大多数问题


 ArXoR 回复于:2007-03-26 17:20:55

引用:原帖由 njmarshal 于 3/26/07 16:55 发表

你觉得哪里不理解

我上面的代码用a b c代替了 5  2   1 
是这个程序具有扩展性 

可以完成任意3个正整数组合的大多数问题 



在你写的程序里面
b != 1 时能保证所有这些a,b,c加起来等于1000么?
换句话说, b 不一定整除 (1000 - i - b - j * c), 0 <= j*c <= 1000 - i - b.

我的之前给的方法就是基于存在一个1, 能整除2与5, 而且能整除n.

而且要求1,2,5至少都有一个也不是什么问题, 对1000-8=992 求就好了

[ 本帖最后由 ArXoR 于 2007-3-26 17:22 编辑 ]


 njmarshal 回复于:2007-03-26 17:37:33

引用:原帖由 ArXoR 于 2007-3-26 17:20 发表


在你写的程序里面
b != 1 时能保证所有这些a,b,c加起来等于1000么?
换句话说, b 不一定整除 (1000 - i - b - j * c), 0 <= j*c <= 1000 - i - b.

我的之前给的方法就是基于存在一个1, 能整除2与5, ... 




有道理

考虑欠缺

1是很特殊的数字 ,任何整数总可以用他想加得到

确实


 wuxb45 回复于:2007-03-26 18:32:23

int i;
int count=1;
for(i=1000;i;i-=5)
  count+=(i/2+1);
不好意思四行


 wuxb45 回复于:2007-03-26 18:34:11

关键是简化运算步骤而不是怎么写。


 010320223 回复于:2007-03-26 21:28:22

for(i=200;i>=0;i--)
{
      count+=floor(5*i/2)+1;
}


 macer 回复于:2007-03-27 10:51:55

如果是三个数为3,5,7又该怎么考虑呢


 ArXoR 回复于:2007-03-27 11:10:11

引用:原帖由 macer 于 3/27/07 10:51 发表
如果是三个数为3,5,7又该怎么考虑呢 



用生成函数, 求 1 / (1 - x^3) * 1 / (1 - x^5) * 1 / (1 - x^7) 展开式中x^n的系数.
已经有系统的方法来计算了,
能不能求出close form没试不知道.

可以参考<<Concrete Mathematics>>


 dbcat 回复于:2007-03-27 12:03:17

3,5,7的母函数还是写成(1+x^3+x^6+x^9+.....)(1+x^7+x^14+x^21+...)(1+x^5+x^10+x^15+...)让大家好理解些


 lenky0401 回复于:2007-03-27 18:42:36

引用:原帖由 liuke432 于 2007-3-24 00:28 发表
不好意思,我没有表达明白意思。
我的意思其实是要求效率再高一点。 



其实他们都懂你的意思了 只是和你开玩笑而已


 macer 回复于:2007-03-28 14:10:30

怎么现在都记不起来这些了呢?昨天一收到回复就去查看了下,结果什么都记不起来啦


 chen_gxing 回复于:2007-03-28 16:17:49

好贴,好问题。


 Darkcoming 回复于:2007-03-31 14:53:27

对这种编程不太懂  数学学得不好  不过要我解决  我就会用公倍数作为突破点  相信效率是最高的

[ 本帖最后由 Darkcoming 于 2007-3-31 15:00 编辑 ]


 王紫豪 回复于:2007-04-04 01:56:54

00000000000


 gta 回复于:2007-04-06 22:05:01

好帖,留名




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=914208
转载请注明作者名及原文出处



收藏本页到: