gxqcn 发表于 2013-8-16 21:37:04

现在这个问题我已经有比较成熟算法了,只是要用到浮点数据类型。

zeroieme 发表于 2013-8-17 13:39:59

引入超前项 1之后,就变成求比例q的方程 (q^n-1)/(q-1)=(Sum(an)+1)

mathe 发表于 2013-8-17 20:33:19

1,10,100,1000,10000公比变化范围不是0吗,不全是10 吗,9从哪来

mathe 发表于 2013-8-17 20:38:31

而这个题还有麻烦之处在于答案可能不唯一,比如和21,n为3,可以7,7,7也可3,6,12

mathe 发表于 2013-8-17 20:42:24

看到,相当于最前面添加了1,那么基本没什么选择自由了

gxqcn 发表于 2013-8-17 20:42:30

{7,7,7} 的比例动态范围=7-1=6;
{3,6,12}的比例动态范围=3-2=1;
后者优于前者。

注意:$q_0=a_0$

KeyTo9_Fans 发表于 2013-8-18 13:25:46

当$n=2$时,

$a_0=A000196(s)$
$a_1=A028391(s)$

其中:

$A000196(n)=\lfloor\sqrt{n}\rfloor$
https://oeis.org/A000196

$A028391(n)=n-\lfloor\sqrt{n}\rfloor$
https://oeis.org/A028391

两个数列均需要求平方根,很难避免实数运算。

当$n>2$时,在oeis里面找不到答案。

zgg___ 发表于 2013-8-22 16:20:27

可以用12层的公式呀,然后用二分法求根,因为根是整数,所以几次就够了。得到了公比q,各项再调整一下就ok了,呵呵。

gxqcn 发表于 2013-8-22 16:32:56

关键是根不见得是整数啊,比如:把100打散成8项。

liangbch 发表于 2013-8-22 18:23:12

我的程序计算的结果是{6,37,234,1479,9355},比8楼的结果更均衡。
这个程序只对第二项以后的数进行调整,楼主可改良一下,看看是否在某些情况下,调整首项更好些。
下面是全部源代码。#include "stdio.h"
#include "stdlib.h"
#include "math.h"

void calc_max_min_ratio(int arr[], int len, int* pIdx_max, int* pIdx_min)
{
        int i,idx_max,idx_min;
        double max,min;

        idx_max=idx_min=0;
        min=max=(double)arr / (double)arr;
        for (i=1;i<len-1;i++)
        {
                if( (double)arr / (double)arr > max)
                {
                        max=(double)arr / (double)arr;
                        idx_max=i;
                }
               
                if( (double)arr / (double)arr < min)
                {
                        min=(double)arr / (double)arr;
                        idx_min=i;
                }
        }
        *pIdx_max=idx_max;
        *pIdx_min=idx_min;
}

void split_int(int s,int n, int arr[] )
{
        double q0,q1;
        double qMin, qMax;
        int i,idx_max,idx_min,s1,s2;

        q0=pow( (double)s,1.0/(double)n);
        arr=(int)q0;

        for (i=1;i<n;i++)
                arr=(int)( (double)arr * q0);
       
        for (s1=0,i=0;i<n;i++)
                s1+=arr;

        calc_max_min_ratio(arr,n,&idx_max,&idx_min);
       
        //printf("s1=%d\n",s1);
        //printf("max ratio is %.6f\n", (double)arr/(double)arr);
        //printf("min ratio is %.6f\n", (double)arr/(double)arr);

        //以下迭代过程调整数组的公比
        while (s1 != s)
        {
                if (s1>s)//降低公比
                {
                        arr--;
                        q1=(double)(arr)/(double)(arr) ;
                       
                        for (i=idx_max+2;i<n;i++)
                                arr=(int)( (double)arr * q0);
                }
                else                //增加公比
                {
                        arr++;
                        q1= (double)(arr)/(double)(arr);
                       
                        for (i=idx_min+2;i<n;i++)
                                arr=(int)( (double)arr * q0);
                }
               
                calc_max_min_ratio(arr,n,&idx_max,&idx_min);
               
                for (s2=0,i=0;i<n;i++)
                        s2+=arr;
               
                if (s1>s && s2<s)
                        break;
                else if (s1<s && s2>s)
                        break;
               
                s1=s2;
                q0=q1;

                //printf("s1=%d\n",s1);
                //printf("max ratio is %.6f\n", (double)arr/(double)arr);
                //printf("min ratio is %.6f\n", (double)arr/(double)arr);
        }
       
        if (q1<q0)
        {
                double t;
                t=q0; q0=q1; q1=t;//q0是公比期望下限, q1是公比期望上限
        }

        if (s2==s)
                return;
        else if (s2<s)
                arr += ( s-s2);
        else
                arr -= ( s2-s);
       
       
        //以下迭代过程对数组各个元素进行微调
        while ( 1)
        {
               
                double tq,d;

                tq=(q0+q1)/2;
               
                calc_max_min_ratio(arr,n,&idx_max,&idx_min);
                qMin=(double)(arr)/(double)(arr) ;
                qMax=(double)(arr)/(double)(arr) ;
                //printf("max ratio is %.6f\n", qMax);
                //printf("min ratio is %.6f\n", qMin);

                if (qMax>q1) //某2项的比超过期望值
                {
                        d= ((double)(arr) - (double)(arr) * tq)/(tq+1) ;
                        if ( fabs(d)<0.6)
                                break;
                        arr -= (int)d;
                        arr += (int)d;
                }
                else if ( qMin<q0)        //某2项的比低于期望值
                {
                        d= ( (double)(arr) * tq -(double)(arr))/(tq+1) ;
                        if ( fabs(d)<0.6)
                                break;
                        arr += (int)d;
                        arr -= (int)d;
                }
                else
                {
                        break;
                }
        }

        printf("array is {");
        for (s1=0,i=0;i<n;i++)
        {        s1+=arr; printf("%d,",arr); }
        printf("}\nsum is %d\n",s1);
       
        calc_max_min_ratio(arr,n,&idx_max,&idx_min);
        qMin=(double)(arr)/(double)(arr) ;
        qMax=(double)(arr)/(double)(arr) ;
        printf("max ratio is %.6f\n", qMax);
        printf("min ratio is %.6f\n", qMin);
}


int main(int argc, char* argv[])
{
        int s,n;
        int arr;

        s=11111;
        n=5;

        split_int(s,n,arr);

        return 0;
}

页: 1 [2] 3 4 5
查看完整版本: 将一正整数打散成指定长度的近似等比整数数列