要求是这样的,随机取一个100000以下的数字a,然后要求产生1个随机数字b,b要可以被a整除,比如随机产生了一个88888(a),然后随机取出一个能被其整除的22(b)我原来的算法是for i=1;i<=a; i++,然后一个一个试,将结果放进一个数组,然后在这个数组里随机取一个,这样实在太傻了,可是又想不出更好的办法,哪位能帮帮忙?

解决方案 »

  1.   

    用mod 2,然后mod3 ...的方法可能快一点
      

  2.   

    For...Next还是要For...Next!
    就算有个函数有这样的功能,但函数体内也应该是For...Next!不清楚~数学差~!可能找个会"速算"的大侠可以想到办法!
      

  3.   

    1、在1至100000中取随机数C;
    2、在1至(100000 / C)取随机数D;
    3、取A=C*D,B随便取C或D;
    呵呵,没准符合你的要求。
      

  4.   

    for i=1;i<=int(sqrt(a)); i++,
    c语言里面好像是这样开方取整的int(sqrt(a)),时间长了记不清了。这样你可以大大降低运算量,算到这个数如果都还没找到,那就说明是素数了。
      

  5.   

    有个算法专门干这个事情
    叫做欧基里德辗转相除法,可以判定两个数是否互质!
    具体步骤好像是把两个数相除,如果有余数则取余数和除数(被除数就不再需要了)继续除,如果最后得到1就表示互质,否则就不互质.不一定准确,我记不太清了(随机取的两个数多半互质,呵呵,当然不能都为偶数).你这实际上就是rsa的一部分.
      

  6.   

    只要循环到a/2就可以了,例如:
    88888(a)=2×44444->把2和44444分别存到数组里
    88888(a)=4×22222->把4和22222也分别存到数组里
    .
    .
    .
    循环到了88888(a)=44444×2时,这两个数已经在数组里了,所以44444-88888这段循环可以省下来,理论应该可以快一倍。。
    期望有更好的算法
      

  7.   

    88888(a),22(b)
    是不是888888,222的意思 ???你用c在vb中間並不適合
      

  8.   

    你可以先随机取数,然后判断能否整除,不行再来过就是了
    =======================================================
    假设已得出第一个随机数88888(a),再取第二个随机数(b)去验证它是否能被88888整除,但是在理论上,你有可能取一千万次随机数(b)都等于同一个不能被88888整除的数(例如3),即使这样的可能极小。。同样,你也有可能取一千万次随机数b,它们虽然不是都等于同一个不能被88888整除的数,但却很有可能都等于不能被88888整除的一些数(例如5,9,3等等)这样做法好像不太严谨
      

  9.   

    假如是我,我会这样做:
    先将大数分解因子,将因子存入一个数组,
    用时,顺手拎几个因子出来乘一下就可以了(没忘了比大小)      ----------------------------------------------- 
          我编了三年程序                只用过VB 
          我用了三年VB         只会WINSOCK和加密
           http://www.offca.com/gps/iphonebbs/
          **********中国网络程序开发联盟欢迎你**********
          -----------------------------------------------
      

  10.   

    也不至于很慢:Private Sub Command1_Click()
    GETRAN
    End SubSub GETRAN()
    Dim X As Long
    Dim FACTOR As New Collection
    Set FACTOR = Nothing
    Randomize
    X = Int(Rnd * 10000 + 1)
    FACTOR.Add 1
    For I = 2 To X / 2
    If X Mod I = 0 Then FACTOR.Add I
    Next
    FACTOR.Add X
    MsgBox "NUMBER:  " & X & vbCrLf & "FACTOR:  " & FACTOR(Int(Rnd * FACTOR.Count) + 1)End Sub
      

  11.   

    lsftest() 讲得对,我的所谓"算法"不一定有输出的,呵呵.cnTOMcn() 的算法应该算是比较可行的,不过是要分解质因数,不知道还有没有更好的.
      

  12.   

    Dim i As Long, tmp As Long, a As Long, b As Long
        Dim cnt As Long
        Randomize
        
        '方法一
        For i = 1 To 1000
            cnt = cnt + 1
            tmp = Int(Rnd * 10000 + 1)
            b = Int(Rnd * 10000 + 1)
            a = tmp * b
            If a > 10000 Then
                i = i - 1
            Else
                Debug.Print a & "/" & b & "="; a / b
            End If
        Next i
        
        Debug.Print "cnt="; cnt
        Exit Sub
        
        '方法2 同 986753421(做点什么?) 
        For i = 1 To 1000
            tmp = Int(Rnd * 10000 + 1)
            b = Int(Rnd * (10000 \ tmp) + 1)
            a = tmp * b
            Debug.Print a & "/" & b & "=" & a / b
            DoEvents
        Next i
        方法一 从效率上来说, 是方法二的10000倍,因为数范围为1~10000*10000
           从随机分布上来说, 明显好于方法二. 对于你的要求可以用一来实现
           具体可以执行观看结果.
      

  13.   

    上面的, 效率约为方法二的1050次. 可以用cnt/1000观看.
      

  14.   

    方法一 从效率上来说, 是方法二的10000倍,因为数范围为1~10000*10000
           从随机分布上来说, 明显好于方法二. 对于你的要求可以用一来实现
           具体可以执行观看结果.
    ===========================
    我想你可能理解错了986753421(做点什么?) 的意思,他的意思应该是这样的:先求数B,再求数A:
    Private Sub Command1_Click()
    Randomize
    Dim a, b, step As Long
    b = Int(100000 * Rnd + 1)
    step = Int(100000 / b)
    '从2到step取随机数temp
    TEMP = Int((step - 1) * Rnd + 2)
    a = b * TEMP
    Print Str(a) + "/" + Str(b) + "=" + Str(TEMP)
    End Sub
    根本不必用循环,是好方法只是不知合不合楼主的要求。
      

  15.   

    方法一 从效率上来说, 是方法二的10000倍,因为数范围为1~10000*10000
           从随机分布上来说, 明显好于方法二. 对于你的要求可以用一来实现
           具体可以执行观看结果.
    ===========================
    我想你可能理解错了986753421(做点什么?) 的意思,他的意思应该是这样的:先求数B,再求数A:
    ==================================================
    我想你可能理解错了 pigsanddogs(我爱吃猪肉,但是长不胖,为什么??) 的意思, :)
      

  16.   

    我想你可能理解错了 pigsanddogs(我爱吃猪肉,但是长不胖,为什么??) 的意思, :)
    ================================================================
    哦,对不起,是的,刚才是我没有认真看兄台的代码,原理是差不多。但我不赞同你说的方法一比方法二好的说法,楼主的要求是随机取一个100000以下的数字a,但兄台所取的两个随机数:
    tmp = Int(Rnd * 10000 + 1)
    b = Int(Rnd * 10000 + 1)
    max(temp)×max(b)=10000×10000=100000000>>100000,但我估计这可能是兄台的笔误吧。
    但如果把程序改成:
    tmp = Int(Rnd * 100 + 1)
    b = Int(Rnd * 1000 + 1)
    max(temp)×max(b)=100×1000=100000是可以,但却不能产生真正的随机,用上面这样的取数方式,有些数会被忽略了,例如,就产生不了88888(a)=44444×2这样的数,因为无论temp还是b都不会等于44444。
    如果我理解错了,还请兄台指出。
      

  17.   

    目的是取出三个数么?还是根据条件取出两个数?
    三个数可以反过来取呀
    在范围内随机取出a,根据a缩小范围随机取出b,相乘得到第一个数
      

  18.   

    TO:kkkksunday(我是猪小弟)
    楼主应该是要两个数!
        一个10000之内的随机数A.
        一个可以整除A的B.而B,则是所有可以整除A的数里的随机一个这个算法有搞头呵呵!
      

  19.   

    88888 \ 22 = 4040.3636363636363636363636363636TO:victorycyz(中海)
    应该是举个例子吧~!没别的意思的.呵呵
      

  20.   

    max(temp)×max(b)=10000×10000=100000000>>100000,但我估计这可能是兄台的笔误吧。
    但如果把程序改成:
    tmp = Int(Rnd * 100 + 1)
    b = Int(Rnd * 1000 + 1)
    max(temp)×max(b)=100×1000=100000是可以,但却不能产生真正的随机,用上面这样的取数方式,有些数会被忽略了,例如,就产生不了88888(a)=44444×2这样的数,因为无论temp还是b都不会等于44444。
    ==============================>
    确实如此. 如果让tmp,b都在100这个范围取值. 能满足a=b*tmp的条件,但
      

  21.   

    接上面. 回车不好使;
    能满足条件, 但如上,不能产生真正的随机数字
    所以为了让tmp,b都是"真正"的随机数, 所以在方法一中,我让他们都在10000取值
    但这样,可能他们的值会比10000大,也可能比10000小. 所以,如果比10000大的,这次取
    值就忽略掉; 所以有个概率问题, 就是说要大概1000多次才能取到一个这样的值.
    但对于楼主来说,从随机分布来说, 从现在计算机的处理速度来说,这算不上什么.
    所以我推荐用这个方法. 请你把代码运行看看. 然后让cnt/1000大概就知道平均算出
    一个这样的值需要取多少次值.
    方法二虽然每次都能运算出, 但也不能算是"真正"的随机, 诚然, 他也可能获取
    满足条件的任意组合, 但b,tmp都获中间(即都小于100)的概率是很小.
    因为tmp从概率上说, 算平均的话, 应该是5000, 那么b的范围一般都是在1,2之间
    这样也就是说, 最后运算出来的b,一般都是1,2很小的数字,概率上不算随机另;方法一; max(tmp) * max(b) = 10000 * 10000 是10000的10000倍
    但任意rnd a *  rnd b < 10000的概率却不是成正比关系, 可以用下面代码算出
    dim i as long , j as long ,cnt
    for i = 1 to 10000
    for j = 1 to 10000
       if i * j < 10000 then cnt = cnt + 1
    next j
    next i 
    debug.print 10000& * 10000 / cnt大概  1067.88547996113 次就能取到一个那样的值
      

  22.   

    方法二虽然每次都能运算出, 但也不能算是"真正"的随机, 诚然, 他也可能获取
    满足条件的任意组合, 但b,tmp都获中间(即都小于100)的概率是很小.
    因为tmp从概率上说, 算平均的话, 应该是5000, 那么b的范围一般都是在1,2之间
    这样也就是说, 最后运算出来的b,一般都是1,2很小的数字,概率上不算随机
    =======================================================================
    不同意,temp如果是真的随机数,从概率来说,它就应该在1~100000(重复一次,楼主要的值是100000以下)里面任意取值,各个数的机会均等,不能说temp=5000的机会就比temp=10的机会多。。我觉得这样算平均不合理。
      

  23.   

    不知楼主是纯粹讨论算法还是有实际应用?如是实际应用,有个比较另类的方法:
    先选择一个比较小的B,再顺手乘个因子,得到A。
    OK,交差。
    “报告老师,我做好了!”:)
      

  24.   

    据我理解,这不是简单的算法!
    1.首先随机取得一个a,然后使用“某种算法”随机取得一个b,使得mod(a/b)=0
    2.关键,这里随机取一个b,至少需要使用一次Rnd()函数吧,由于使用了Rnd()这个函数,使得b具有不可预测性。
    3.按照楼主的思路看,这个b不是一个真正的随机数,只是一个预赋值好的数组中随机成员!
    4.这样,如果,单纯使用穷举遍历所有小于a的所有的整数,又不能满足“随机获得”b的要求,使用while...wend语句,那就有可能“死机”
      

  25.   

    不同意,temp如果是真的随机数,从概率来说,它就应该在1~100000(重复一次,楼主要的值是100000以下)里面任意取值,各个数的机会均等,不能说temp=5000的机会就比temp=10的机会多。。我觉得这样算平均不合理。
    =======================================================================
    算法二: 是这样的,虽然temp=5000和temp=10和temp=1的机会是一样的多, 但
            b(100000\temp) 为5000,10,1的机会却不是一样的多, rnd()*(100000\temp+1)
            也不是, 因为整除号已经做了近似处理。 而楼主希望a,b都是“真正的”随机,
            而不是中间值temp
            做个假设:
            假设随机了100000次,并且很公平的从1-100000都有值,  那么b为1的概率为50%。
            因为大于50000的数被100000整除都为1, 而实际中( rnd()*(100000\temp+1 )为1的
            概率还要大于50%,因为实际的值是在上面的(1~~b)中取出来的。所以我觉得
            这个方法不是“真正的随机数字”
            可以把代码运行一遍, 我觉得结果最有说明力
    另:抱歉,我没仔细看题目,把100000看成了10000,所以里面所有的10000都要替换成100000
        并且在方法一中,需要用cdbl转换,100000*100000会溢出,,
      

  26.   

    利用系统函数获得随机数 a再利用系统函数获得随机数 b通过加减修改 b 值以达到整除。这样算法复杂度很小。也达到随机的目的。
      

  27.   

    典型算法为:1. 范围:{1,2,3,...,Max}=E;
    2. 输入:A in E;
    3. 范围:{1,...(A Mod 2)}=F;
    4. 搜索所有B in F,使得A Mod B =0,得到B的集合{B};
    5. 然后在集合{B}中随机取B(i)作为输出,{B}为空,则输出空。如果是考虑算法效率问题,关键在第四步;如果想从搜索一开始便随机取值,以期获得随机性且满足条件的话,除非A、B存在必然数值关系,否则这种想法是不切实际的。跟楼主思路一样!~:) 只是可以在加快搜索速度上可以改进!
      

  28.   

    Dim i    As Long
    Dim j    As Long
    Dim Flag As Boolean    Randomize
        i = CLng(Rnd * 10000)
           
        'MsgBox i
            
        Randomize
        
        Flag = False
        
        For j = 2 To CLng(Sqr(i))
            If i Mod j = 0 Then
               Flag = True
               Exit For
            End If
        Next
        
        If Flag = False Then
            MsgBox i & "不能被任何数整除!", vbInformation + vbOKOnly, "系统提示"
        Else
            MsgBox i & "能被" & j & "整除!", vbInformation + vbOKOnly, "系统提示"
        End If
      

  29.   

    算法二: 是这样的,虽然temp=5000和temp=10和temp=1的机会是一样的多, 但
            b(100000\temp) 为5000,10,1的机会却不是一样的多, rnd()*(100000\temp+1)
            也不是, 因为整除号已经做了近似处理。 而楼主希望a,b都是“真正的”随机,
            而不是中间值temp
    ==========================================================
    是会有这样的情况,但这种情况并不是由于算法或计算失误所造成的(取整可能会有一点点影响),而是由题目本身的要求所造成的,b的取值受a的约束,a必然小于100000,而b是a的因数,即必须与另一数(temp)相乘才等于a。temp最小的取值为2,由上面可知:
    a<=100000
    a=b*temp
    temp>=2
    可得出b<=50000,所以不能要求b在1~100000以内随机。可以把代码运行一遍, 我觉得结果最有说明力
    ==========================
    虽然都是用第二种方法的思路,但我的步骤与你的有些不同,因为楼主只要求两个随机数,所以temp的值其实并不重要,我的方法是先保证数b的随机性,但如上所说,如果保证了b的随机性,就必然会影响a的随机性,由下面代码的测试结果证明了这一点,a大于50000与a小于50000的比例大概是8:2(我上面的代码里b的取值范围也错了,应该在1~50000之间而不是1~100000之间):
    Private Sub Command1_Click()
    Randomize
    Dim a, b, step As Long
    Dim upa, lowa As Long
    For i = 1 To 100000
    b = Int(50000 * Rnd + 1)
    step = Int(100000 / b)
    '从2到step取随机数temp
    TEMP = Int((step - 1) * Rnd + 2)
    a = b * TEMP
    'Print Str(a) + "/" + Str(b) + "=" + Str(TEMP)
    If a > 50000 Then
    upa = upa + 1
    Else
    lowa = lowa + 1
    End If
    Next
    Print upa, lowa, upb, lowb
    End Sub
    至于认为方法一不理想,是因为觉得这种方法把有些可能性忽略了,两害相权取其轻。。
    要真正的随机,或许真的要回到老路(穷举a/2个数)上????
      

  30.   

    to : lsftest() 呵呵, 都对都对哈
    主要是楼住问题不明确, 你那红外控制搞的怎么样了?
    今天升星了,高兴的啊。
      

  31.   

    你那红外控制搞的怎么样了?
    =================================
    不太顺利,红外接收那部分应该没有什么问题了,但我的目的是用来控制另一个程序:我有一张ati的电视卡可以接收电视,在它的播放程序里有一个按钮,点击就可以换频道,或者按“+”键也可以,我就是想用遥控控制它的频道转换,那么就可以躺在床上看电视了(懒人本色,呵呵)。。问题是不知道怎么往按钮发消息。。找到了按钮的hwnd,向它sendmessage,keydown,keyup,wm_char,都试过了,都没有反应。。用sendkeys “+”也不行用myspy跟踪它接收的消息然后按“+”键,频道是变了,但myspy却显示那个按钮没有接收到这个按钮消息,真不知是哪个窗口接收了去郁闷ing。今天升星了,高兴的啊。
    ====================
    恭喜恭喜,高人就是不一样,我在csdn呆了一年多才蹭了五个裤衩,惭愧啊。。
    顺带问一句,要多少分才能升星??