求算法

zengpeiwen 2012-03-14 09:47:49
现有C_m_n(27,7)=888030,即只能在1,2,3...-27个号码中选7个号码的去组合,假设每一个组合初始时只能选100次

01,02,03,04,05,06,07 100次
.
.
.
21,22,23,24,25,26,27 100次


假如现在我买 01,03,04,05,06,10,11,17,19,20,21,22,23,25,27 15个号码
这时候我就需要去判断这C_m_n(15,7)中的每一组号码是否超出了 100次的上限,
如何去快速查找我买的每一个组合目前的上限呢?

用二分法也不行,因为我必须在1秒内必须完成这个查找(服务器性能是很高的).
...全文
283 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
zengpeiwen 2012-03-15
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 freefice 的回复:]
第一个是03,则01,02,是满的全组合,则03的基数为C26^6+C25^6
第二个是04,基数为0
第三个是06,则05是满的,06的基数为C21^4;
第四个是08,则07是满的,08的基数为C19^3;
……
03040608101326对应的序号为C26^6+C25^6+C21^4+C19^3+C17^2+C15+C14+(26-14);
你可以简化一下,也可以用数组将每位的……
[/Quote]
不好意思,还是没看明白,假设下面的组合
abcdefg
其标准公式是什么?
lanmeng521131485 2012-03-15
  • 打赏
  • 举报
回复
学习中 卡呢不是很懂啊@!!看来要努力啊!!
庄鱼 2012-03-15
  • 打赏
  • 举报
回复
第一个是03,则01,02,是满的全组合,则03的基数为C26^6+C25^6
第二个是04,基数为0
第三个是06,则05是满的,06的基数为C21^4;
第四个是08,则07是满的,08的基数为C19^3;
……
03040608101326对应的序号为C26^6+C25^6+C21^4+C19^3+C17^2+C15+C14+(26-14);
你可以简化一下,也可以用数组将每位的基数算好到时直接读取,避免二次计算,这样,你的查找速度将进入ns级(看在什么机器上)。
zengpeiwen 2012-03-15
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 freefice 的回复:]
如果,你是按由小到大循环存放的,由于是组合,不存在重合问题因此c1-1,c2-2,c3-3……计算各自序列后续个数将其存放在数组中,这样,计算各数字与相关位数的阶差,通过累加就可以得出序号。
[/Quote]

能详细点吗,或者举个例子?
03040608101326
怎么算
laoyang103 2012-03-15
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 hnu_0720 的回复:]

引用 13 楼 zengpeiwen 的回复:

我在想 因为每一个组合数是已知且唯一的,有什么方法直接对应到一个数组下标就好了。比如
01020304050607 下标0
01020304050608 下标1
01020304050609 下标2
...
...

21222324252627 下标888029

这样就根本不用查找了,就可以直接定位了。。……
[/Quote]

明显是康拓展开式 你去写个代码让我运行一下吧 我负责给你测试

如果我测试完了正确 我一定会好好学习你的代码
庄鱼 2012-03-15
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 hnu_0720 的回复:]

引用 13 楼 zengpeiwen 的回复:

我在想 因为每一个组合数是已知且唯一的,有什么方法直接对应到一个数组下标就好了。比如
01020304050607 下标0
01020304050608 下标1
01020304050609 下标2
...
...

21222324252627 下标888029

这样就根本不用查找了,就可以直接定位了。。……
[/Quote]
你该把体看清楚,是组合而不是排列
zengpeiwen 2012-03-15
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 hnu_0720 的回复:]
引用 13 楼 zengpeiwen 的回复:

我在想 因为每一个组合数是已知且唯一的,有什么方法直接对应到一个数组下标就好了。比如
01020304050607 下标0
01020304050608 下标1
01020304050609 下标2
...
...

21222324252627 下标888029

这样就根本不用查找了,就可以直接定位了。。。。

每次引……
[/Quote]

这个是算某一个组合在全排列的位置的,和我问题对不起来
hnu_0720 2012-03-15
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 zengpeiwen 的回复:]

我在想 因为每一个组合数是已知且唯一的,有什么方法直接对应到一个数组下标就好了。比如
01020304050607 下标0
01020304050608 下标1
01020304050609 下标2
...
...

21222324252627 下标888029

这样就根本不用查找了,就可以直接定位了。。。。
[/Quote]
每次引用都搞错.无语.
{1,2,3,4,...,n}表示1,2,3,...,n的排列如 {1,2,3} 按从小到大排列一共6个。123 132 213 231 312 321 。

代表的数字 1 2 3 4 5 6 也就是把10进制数与一个排列对应起来。

他们间的对应关系可由康托展开来找到。

如我想知道321是{1,2,3}中第几个大的数可以这样考虑 :

第一位是3,当第一位的数小于3时,那排列数小于321 如 123、 213 ,小于3的数有1、2 。所以有2*2!个。再看小于第二位2的:小于2的数只有一个就是1 ,所以有1*1!=1 所以小于321的{1,2,3}排列数有2*2!+1*1!=5个。所以321是第6个大的数。 2*2!+1*1!是康托展开。

再举个例子:1324是{1,2,3,4}排列数中第几个大的数:第一位是1小于1的数没有,是0个 0*3! 第二位是3小于3的数有1和2,但1已经在第一位了,所以只有一个数2 1*2! 。第三位是2小于2的数是1,但1在第一位,所以有0个数 0*1! ,所以比1324小的排列有0*3!+1*2!+0*1!=2个,1324是第三个大数。
hnu_0720 2012-03-15
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 hondely 的回复:]

http://blog.csdn.net/hondely/article/details/6984777
[/Quote]
用康拓展开式啊
上面的大神已经说过了!
庄鱼 2012-03-15
  • 打赏
  • 举报
回复
举个简单的例子:abcdefg,三个字母组合有多少种呢C7^3:
abc abd abe abf abg acd ace acf acg ade adf adg aef aeg afg
bcd bce bcf bcg bde bdf bdg bef beg bfg
cde cdf cdg cef ceg cfg
def deg dfg
efg
如果首字母为a,则基数为0,为b则基数为C6^2=15,为c就是C6^2+C5^2=20……
第二位,则根据第一位定位计算,如顺序则基数为0,间隔则为间隔数对应组合为基数,如ade就是C5+C4=9
以此类推。数学该补一下了。
庄鱼 2012-03-14
  • 打赏
  • 举报
回复
你用switch-case,或下标不久可以直接定义到目标,了解其次数还不简单吗?有什么性能问题?比方说当前是3,你就读N[3-1]不就得了
zengpeiwen 2012-03-14
  • 打赏
  • 举报
回复
有高手没啊???
zengpeiwen 2012-03-14
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 freefice 的回复:]
简单阿,你申请一个char stat[27]={0};就可以了;
当你组合到哪位元素时,就对相应的元素+1,当元素使用超过100次,就不再读取
你也可以将27个元素建成标记环,用到的元素标记+1,超出100时,从环中剔除
还有…………
很多方法,你可以自己想想啊,很简单的
至于产生数丢池子里就行了
[/Quote]
现在主要是考虑性能的问题。也就是如果快速查找元素的当前值是多少?
庄鱼 2012-03-14
  • 打赏
  • 举报
回复
简单阿,你申请一个char stat[27]={0};就可以了;
当你组合到哪位元素时,就对相应的元素+1,当元素使用超过100次,就不再读取
你也可以将27个元素建成标记环,用到的元素标记+1,超出100时,从环中剔除
还有…………
很多方法,你可以自己想想啊,很简单的
至于产生数丢池子里就行了
zengpeiwen 2012-03-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 laoyang103 的回复:]
引用 1 楼 vanxeger_2 的回复:

大哥,你不能搞一个标记位么?!icount++!这个就不用1S了!


呵呵 请问这个朋友如何定位 比如我给你1 2 3 4 5 7 你怎么就知道它在状态空间的第一位

给你21,22,23,24,25,26,27你又如何知道在最后一位 任意给你一个 x1 x2 x3 x4 x5 x6 x7

你又如何能计算出它在状态空间的位置
[/Quote]


是的,我的意思也就是最好一次就能定位到位置,类似康拓展开式这些算法。。
庄鱼 2012-03-14
  • 打赏
  • 举报
回复
如果,你是按由小到大循环存放的,由于是组合,不存在重合问题因此c1-1,c2-2,c3-3……计算各自序列后续个数将其存放在数组中,这样,计算各数字与相关位数的阶差,通过累加就可以得出序号。
laoyang103 2012-03-14
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 vanxeger_2 的回复:]

大哥,你不能搞一个标记位么?!icount++!这个就不用1S了!
[/Quote]

呵呵 请问这个朋友如何定位 比如我给你1 2 3 4 5 7 你怎么就知道它在状态空间的第一位

给你21,22,23,24,25,26,27你又如何知道在最后一位 任意给你一个 x1 x2 x3 x4 x5 x6 x7

你又如何能计算出它在状态空间的位置
laoyang103 2012-03-14
  • 打赏
  • 举报
回复
呵呵 状态空间定位问题 组合数的状态空间我还真不知道

如果是排列数的状态空间 就可以用康拓展开式在O(1)时间内找到

详情参考
http://bbs.bccn.net/thread-362383-4-3.html
zengpeiwen 2012-03-14
  • 打赏
  • 举报
回复
怎么标记,不解
vanxeger 2012-03-14
  • 打赏
  • 举报
回复
大哥,你不能搞一个标记位么?!icount++!这个就不用1S了!
加载更多回复(9)

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧