整数_输入一个整数a,再输入两个整数p和v整数 - CSDN
  • 返回不小于 value 的下一个整数,value 如果有小数部分则进一位。ceil() 返回的类型仍然是 float,因为 float 值的范围通常比 integer 要大。 例子 1. ceil() 例子  echo ceil(4.3); // 5 echo ceil(9.9
    ceil — 进一法取整 
    说明
    float ceil ( float value )
    返回不小于 value 的下一个整数,value 如果有小数部分则进一位。ceil() 返回的类型仍然是 float,因为 float 值的范围通常比 integer 要大。

    例子 1. ceil() 例子 

    <?php 
    echo ceil(4.3); // 5 
    echo ceil(9.999); // 10 
    ?> 

    floor — 舍去法取整
    说明
    float floor ( float value )
    返回不大于 value 的下一个整数,将 value 的小数部分舍去取整。floor() 返回的类型仍然是 float,因为 float 值的范围通常比 integer 要大。
    例子 1. floor() 例子 

    <?php 
    echo floor(4.3); // 4 
    echo floor(9.999); // 9 
    ?> 

    round — 对浮点数进行四舍五入
    说明
    float round ( float val [, int precision] )
    返回将 val 根据指定精度 precision(十进制小数点后数字的数目)进行四舍五入的结果。precision 也可以是负数或零(默认值)。
    例子 1. round() 例子 

    <?php 
    echo round(3.4); // 3 
    echo round(3.5); // 4 
    echo round(3.6); // 4 
    echo round(3.6, 0); // 4 
    echo round(1.95583, 2); // 1.96 
    echo round(1241757, -3); // 1242000 
    echo round(5.045, 2); // 5.05 
    echo round(5.055, 2); // 5.06 
    ?> 
    intval—对变数转成整数型态
    例子intval() 

    <?php 
    echo intval(4.3); //4 
    echo intval(4.6); // 4 
    ?> 



    展开全文
  • 整数规划

    2019-06-11 21:45:11
    2.1秘籍内容 在上节课的学习过后,相信各位练武之人对于“数学规划”这一武功有个初步的了解,并且学习...那么何为整数规划呢?它和线性规划又有着怎样的区别和联系呢?下面我们来进一步了解一下。 规划中的变量(...

    在这里插入图片描述

    2.1秘籍内容

    在上节课的学习过后,相信各位练武之人对于“数学规划”这一武功有个初步的了解,并且学习了该武功的第一式——线性规划,但对于某些生产进度问题、旅行推销员问题、工厂 选址问题、背包问题及分配问题等线性规划并不能高效的解决并且往往最优解难以满足条件,这时候我们便需要另一个招式——整数规划。那么何为整数规划呢?它和线性规划又有着怎样的区别和联系呢?下面我们来进一步了解一下。
    在这里插入图片描述规划中的变量(部分或全部)限制为整数时,称为整数规划。若在线性规划模型中, 变量限制为整数,则称为整数线性规划。如不加特殊说明,一般指整数线性规划。对于整数线性规划模型大致可分为两类:
    (i)变量全部限制为整数时,称纯(完全)整数规划。
    (ii)变量部分限制为整数的,称混合整数规划。

    整数规划这一招式,可谓是衍生于线性规划,但是又有其独特奥妙之处比如:
    (i) 原线性规划有最优解,当自变量限制为整数后,其整数规划解出现下述情况:
    ①原线性规划最优解全是整数,则整数规划最优解与线性规划最优解一致。
    ②整数规划无可行解。
    例 1 原线性规划为
    min z=x1x_1+x2x_2
    2x1x_1+4x2x_2=5,x10x1 \geq 0x20x2 \geq 0
    其最优实数解为:x1x_1=0,x2x_2=32\frac{3}{2},min z=32\frac{3}{2}.
    若限制整数得:x1x_1=0,x2x_2=1,min z=2.

    (ii) 整数规划最优解不能按照实数最优解简单取整而获得。也就是说关于整数规划最优解的求法应另有其他方式。
    听完上面的讲述,大家是不是有一些头绪了,整数规划的基础实则为线性规划,合理运用上一招式中的修炼三大法,以及我们即将学习的几种修炼方法,相信整数规划问题定能迎刃而解。
    在这里插入图片描述

    2.2招式解析

    2.2.1 (分枝定界法)

    该方法首先是在上个世纪六十年代初由Land Doig 和 Dakin 等“武林高手”提出的。主要思路为,把全部可行解空间反复地分割为越来越小的子集,称为分枝;并且对每个子集内的解集计算一个目标下界(对于小值问题),这称为定界。在每次分枝后,凡是界限超出已知可行解集目标值的那些子集不再进一步分枝,这样,许多子集可不予考虑,这称剪枝。
    听完这些是不是觉得分枝定界法还挺玄妙,但只要我们掌握分枝、定界、剪枝与比较三步修炼大法,下面通过解决一个实际问题,看看这个方法是否行之有效呢。
    例 3 求解下述整数规划
    Max z=40x1x_1+90x2x_2
    在这里插入图片描述
    解: (i)先不考虑整数限制,即解相应的线性规划B,得最优解
    x1x_1=4.8092,x2x_2=1.8168,z=355.8779
    可见问题B的最优解不符合整数条件。这时 z 是问题 A的优目标函数值 z* 的上界,记作z\vec z。而x1x_1=0,x2x_2=0,显然是问题 A的一个整数可行解,这时z=0,是z* 的一个下界,记作z\underline{z}00 \leq z* 356\leq 356
    (ii)因为x1x_1x2x_2当前均为非整数,故不满足整数要求,任选一个进行分枝。设选进行分枝,把可行集分成 2 个子集:
    x1x_1\leq[4.8092]=4,x2x_2\geq[4.8092]+1=5
    因为 4 与 5 之间无整数,故这两个子集的整数解必与原可行集合整数解一致。这 一步称为分枝。这两个子集的规划及求解如下:
    问题B1B_1:Max z=40x1x_1+90x2x_2
    在这里插入图片描述
    最优解为:x1x_1=4.0,x2x_2=2.1,z=349.
    问题B2B_2:Max z=40x1x_1+90x2x_2
    在这里插入图片描述
    最优解为:x1x_1=5.0,x2x_2=1.57,z=341.4.
    再定界:0\leq z* \leq 349.
    (iii)对问题 再进行分枝得问题B11和B12,它们的最优解为:
    B11x1x_1=4.0,x2x_2=2.0,z11=340.
    B12x1x_1=1.43,x2x_2=3.0,z12=327.14.
    再定界:340 \leq z* \leq 341,并将B12剪枝。
    (iv)对问题B2再进行分枝得问题B21和B22,它们的最优解为
    B21x1x_1=5.44,x2x_2=1.0,z21=308.
    B22:无可行解。
    将B21,B22剪枝。
    于是可以断定原问题的最优解为:
    x1x_1=4.0,x2x_2=2.0,z*=340.

    从以上解题过程可得用分枝定界法求解纯整数规划和混合整数规划问题的步骤:
    1.首先忽略整数约束求解,求得原问题的最优解X
    2.如果决策变量x;本是整数要求,但是得到的结果X; =u (不是整数),则将原问题归结为2个区域的线性规划求解,这个两个区域为分别增加约束条件
    xix_i \leqceil(u) 和 xix_i \leqfloor(u)
    3.然后分别都这两个规划模型重复上面的步骤,直到满足整数要求为止。
    4.再选出最优解。
    大家现在对于分枝定界法求解整数规划问题应该有了一定的了解,除此之外我们还有几种很实用的招式供大家学习了解。我们一起看看吧。
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190611213740337.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h3bmlrYQ==,size_16,color_FFFFFF,t_70#pic_center ==200x150)

    2.2.2 0-1型整数规划

    所谓0-1型整数规划就是变量的取值只能是0或者1,这样的话,其实我们可以将不同的整数规划转化成0-1规划。下面我们来看一个实际问题在这里插入图片描述这里我们就可以直接列出一个是0-1规划的方程,设的变量xix_i,“1”表示被选中,“0”表示没被选中。0-1型整数规划的特点就是相互排斥的约束条件可以转化成同类型的。比如:
    在这里插入图片描述

    2.2.3其他三种方法

    (1)穷举法,是一种很有效的方法,而且在某些情况下只能穷举。
    (2)过渡隐枚举法
    1.先试探性求一个可行解X(随便带入求值)
    2.然后根据是求极大值还是极小值,如果是求极大值,那么凡是目标值<X的解不必检验是否满足约束条件即可删除,如果是求极小值,那么凡是目标值>X不必检验是否满足约束条件就可满足。
    3.改进新的过滤条件
    4.然后验证目标值,最终求得。
    (3)蒙特卡洛法(随机抽样法)
    就是选择不穷举全部点,而是采用随机的方式来抽取样本估计整体,如果样本足够大,可信度是很大的。
    在这里插入图片描述

    2.3武器栏

    只见蓝光一闪,MATLAB之剑横空出世,正所谓招配剑,方能招招命中。
    解非线性整数规划-----------蒙特卡罗方法
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
    Matlab实现整数规划求解(分枝定界法):

    function r=checkint(x)
    %判断x(i)是不是整数了。是的话r(i)返回1,不是的话,返回0
    %输入参数:x   X向量
    %输出参数:r   R向量
    
    for i=1:length(x)
        if(min(abs(x(i)-floor(x(i))),abs(x(i)-ceil(x(i))))<1e-3)
            r(i)=1;
        else
            r(i)=0;
        end
    
    Function val=isrowinmat(arow,mat)
    %用来判断mat中是否包含与arow一样的向量
    %输入变量:arow    向量
    %         mat     矩阵
    %输出变量:val     1表示有,0表示没有
    val=0;
    rows=size(mat,1);
    for i=1:rows
        temp=(mat(i,:)==arow);
        if length(find(temp==0))==0
            val=1;
            return;
        else
            val=0;
        end; 
    end
    

    function [x,fval,exitflag,output,lambda]=linprogdis(ifint,f,A,b,Aeq,beq,lb,ub,x0,options)
    % 用法
    % [x,fval,exitflag,output,lambda]=lpint(ifint.f,A,b,Aeq,beq)
    % [x,fval,exitflag,output,lambda]=lpint(ifint,f,A,b,Aeq,beq,lb)
    % [x,fval,exitflag,output,lambda]=lpint(ifint,f,A,b,Aeq,beq,lb,ub)
    % [x,fval,exitflag,output,lambda]=lpint(ifint,f,A,b,Aeq,beq,lb,ub,x0)
    % [x,fval,exitflag,output,lambda]=lpint(ifint,f,A,b,Aeq,beq,lb,ub,x0,options)

    if nargin<10, options=[];  end
    if nargin<9,  x0=[];       end
    if nargin<8,  ub=inf*ones(size(f));      end
    if nargin<7,  lb=zeros(size(f));      end
    
    [x,fval,exitflag,output,lambda]=linprog(f,A,b,Aeq,beq,lb,ub,x0,options);
    
    if exitflag<=0        %表示线性规划没有最优解
        return 
    end
    
    v1=find(ifint==1);  %找到需要整数规划的变量的下标
    
    temp=x(v1);%如果不是要求整数规划的就可以返回了。
    if isempty(temp)
        return
    end
    
    v2=find(checkint(temp)==0);
    if isempty(v2)   %都是整数,得到最众解
        return
    end
    
    k=v1(v2(1));
    
    temp1=zeros(1,length(f));
    temp1(k)=1;
    low=floor(x(k));
    if isrowinmat([temp1,low],[A,b])==1
        thisA=A;
        thisb=b;
    else
        thisA=[A;temp1];
        thisb=b;
        thisb(end+1)=low;
    end
    
    [x1,fval1,exitflag1,output1,lambda1]=linprogdis(ifint,f,thisA,thisb,Aeq,beq,lb,ub,x0,options);
    
    
    temp2=zeros(1,length(f));
    temp2(k)=-1;
    high=-ceil(x(k));
    if isrowinmat([temp2,high],[A,b])==1
        thisA=A;
        thisb=b;
    else
        thisA=[A;temp2];
        thisb=b;
        thisb(end+1)=high;
    end
    
    [x2,fval2,exitflag2,output2,lambda2]=linprogdis(ifint,f,thisA,thisb,Aeq,beq,lb,ub,x0,options);
    
    if (isempty(v2) && ((exitflag1>0 && exitflag2<=0 && fval<=fval)||(exitflag2>0 && exitflag1<=0 && fval<=fval2)||(exitflag1>0 && exitflag2>0 && fval<=fval1 && fval<=fval2)))
        disp('error call');
        return ; %表示都是整数
    end
    
    if exitflag1>0&&exitflag2<=0
         x=x1;
         fval=fval1;
         exitflag=exitflag1;
         output=output1;
         lambda=lambda1;
    elseif exitflag1<=0&&exitflag2>0
         x=x2;
         fval=fval2;
         exitflag=exitflag2;
         output=output2;
         lambda=lambda2;
    elseif exitflag1>0 && exitflag2>0
        if fval1<fval2
            x=x1;
            fval=fval1;
            exitflag=exitflag1;
            output=output1;
            lambda=lambda1;
        else
             x=x2;
             fval=fval2;
             exitflag=exitflag2;
             output=output2;
             lambda=lambda2;
        end
    end
    
    展开全文
  • 键盘输入十个数,分别统计0到9,10到99,100以上的数的个数,并显示结果。 DATAS SEGMENT BUF DB 5 DUP('$') BUF1 DB '0' BUF2 DB '0' BUF3 DB '0','$';此处输入数据段代码 DATAS ENDS ...CODES ...

    键盘输入十个数,分别统计0到9,10到99,100以上的数的个数,并显示结果。

    DATAS SEGMENT
    	BUF DB 5 DUP('$')
        BUF1 DB '0'
        BUF2 DB '0'
        BUF3 DB '0','$';此处输入数据段代码  
    DATAS ENDS
    
    STACKS SEGMENT
        ;此处输入堆栈段代码
    STACKS ENDS
    
    CODES SEGMENT
        ASSUME CS:CODES,DS:DATAS,SS:STACKS
    START:
        MOV AX,DATAS
        MOV DS,AX
        MOV CX,10
    SHURU:
    	MOV BX,0
    SHURU1:
    	MOV AH,01H
    	INT 21H
    	INC BX
    	CMP AL,0DH
    	JNE SHURU1
    	DEC BX
    	MOV DL,0DH
    	MOV AH,02H
    	INT 21H
    	MOV DL,0AH
    	MOV AH,02H
    	INT 21H
    	CMP BX,1
    	JE YIWEI
    	CMP BX,2
    	JE ERWEI
    	INC BUF3
    	JMP E
    	YIWEI:
    	INC BUF1
    	JMP E
    	ERWEI:
    	INC BUF2
    E:	
    	LOOP SHURU
    OUTPUT:
    	LEA DX,BUF1
    	MOV AH,09H
    	INT 21H
        ;此处输入代码段代码
        MOV AH,4CH
        INT 21H
    CODES ENDS
        END START
    
    
    

    结果图:

    输出结果262表示有2个10以内的,有6个在10~99,有2个100及100以上的

    展开全文
  • 整数划分问题是算法中的一个经典命题之一   所谓整数划分,是指把一个正整数n写成如下形式: n=m1+m2+m3+....+mi;(其中mi为正整数,并且1&lt;=mi&lt;=n),则{m1,m2,m3,....,mi}为n的一个划分。 如果{...

    整数划分问题是算法中的一个经典命题之一

     

    所谓整数划分,是指把一个正整数n写成如下形式:

    n=m1+m2+m3+....+mi;(其中mi为正整数,并且1<=mi<=n),则{m1,m2,m3,....,mi}为n的一个划分。

    如果{m1,m2,m3,....,mi}中的最大值不超过m,即max{m1,m2,m3,....,mi} <= m,则称它属于n的一个m划分。这里我们记n的m划分的个数为f(n,m);

    例如当n=4时,它有5个划分:{4}、{3,1}、{2,2}、{2,1,1}、{1,1,1,1};

    注意:4=1+3和4=3+1被认为是同一个划分。

    该问题是求出n的所有划分个数,即f(n,n)。下面我们考虑求f(n,m)的方法。

     

    方法一:递归法

    根据n和m的关系,考虑下面几种情况:

    (1)当n=1时,不论m的值为多少(m>0),只有一种划分,即{1};

    (2)当m=1时,不论n的值为多少(n>0),只有一种划分,即{1,1,....1,1,1};

    (3)当n=m时,根据划分中是否包含n,可以分为两种情况:

    1. 划分中包含n的情况,只有一个,即{n};
    2. 划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分;

      因此,f(n,n) = 1 + f(n, n - 1)。

    (4)当n<m时,由于划分中不可能出现负数,因此就相当于f(n,n);

    (5)当n>m时,根据划分中是否包含m,可以分为两种情况:

    1. 划分中包含m的情况,即{m,{x1,x2,x3,...,xi}},其中{x1,x2,x3,...,xi}的和为n-m,可能再次出现m,因此是(n-m)的m划分,因此这种划分个数为f(n-m, m);
    2. 划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为f(n, m - 1);

     因此,f(n,m) = f(n - m,m) + f(n, m - 1)。

    综合以上各种情况,可以看出,上面的结论具有递归定义的特征,其中(1)和(2)属于回归条件,(3)和(4)属于特殊情况,而情况(5)为通用情况,属于递归的方法,其本质主要是通过减少n或m以达到回归条件,从而解决问题。

    其递归表达式如下所示。

     

    参考源码1.1(递归版本(较慢))

    #include <stdio.h>
    
    #define MAXNUM 100            //最高次数
    
    //递归法求解整数划分
    unsigned long GetPartitionCount(int n, int max)
    {
        if(n == 1 || max == 1)
        {
            return 1;
        }
        if(n < max)
        {
            return GetPartitionCount(n, n);
        }
        if(n == max)
        {
            return 1 + GetPartitionCount(n, n - 1);
        }
        else
        {
            return GetPartitionCount(n - max, max) + GetPartitionCount(n, max - 1);
        }
    }
    
    
    int main(int argc, char **argv)
    {
        int n;
        int m;
        unsigned long count;
        while(1)
        {
            scanf("%d", &n);
            if(n<=0)
                return 0;
            m=n;
            count = GetPartitionCount(n, m);
            printf("%d\n",count);
        }
        return 0;
    }

     

    方法二:动态规划

    考虑到使用递归中,很多的子递归重复计算,这样不仅在时间开销特别大,这也是运算太慢的原因,比如算120的时候需要3秒中,计算130的时候需要27秒钟,在计算机200的时候....计算10分钟还没计算出来。。。鉴于此,可以使用动态规划的思想进行程序设计,原理如同上面一样,分成三种情况,只是使用一个数组来代替原有的递归,具体可以参看源码,源码中提供了两个版本 递归+记录版本和数组版本

    2.1 递归加记录版本

    此版本使用数组标记,如果之前计算过,则直接调用数组中内容,否则计算子递归,这样保证了每次计算一次,减少冗余量

    源码如下:

     

    /*----------------------------------------------
     *        Author    :NEWPLAN
     *        Date    :2015-04-01
     *        Email    :xxxxxxx
     *        Copyright:NEWPLAN
    -----------------------------------------------*/
    #include <iostream>
    
    
    #define MAXNUM 100            //最高次数
    unsigned  long ww[MAXNUM*11][MAXNUM*11];
    unsigned long dynamic_GetPartitionCount(int n, int max);
    
    using namespace std;
    int main(int argc, char **argv)
    {
        int n;
        int m;
        unsigned long count;
    	
    	while(1)
    	{
    		cin>>n;
    		cout<<dynamic_GetPartitionCount(n,n)<<endl;
    	}
    	
        return 0;
    }
    
    unsigned long dynamic_GetPartitionCount(int n, int max)
    {
        if(n == 1 || max == 1)
        {
    		ww[n][max]=1;
            return 1;
        }
        if(n < max)
        {
    		ww[n][n]=ww[n][n]? ww[n][n] : dynamic_GetPartitionCount(n, n);
    		return ww[n][n];
        }
        if(n == max)
        {
    		ww[n][max]=ww[n][n-1]?1+ww[n][n-1]:1 + dynamic_GetPartitionCount(n, n - 1);
    		return ww[n][max];
        }
        else
        {
    		ww[n][max]=ww[n - max][max]? (ww[n - max][max]) : dynamic_GetPartitionCount(n - max, max);
    		ww[n][max]+=ww[n][max-1]? (ww[n][max-1]): dynamic_GetPartitionCount(n, max - 1);	
            return ww[n][max];
        }
    }

     

     

     

    2.2 数组标记法动态规划(从小到大)

     

    考虑到计算ww[10][10]=ww[10][9]+1;所以在每次计算中都是用到之前的记录,这样就可以先从小到大计算出程序,使得计算较大数的时候调用已经计算出的较小的记录,程序直接是用循环就可以完成任务,避免了重复计算和空间栈的开销。

    源码:

     

    /*----------------------------------------------
     *        Author    :NEWPLAN
     *        Date    :2015-04-01
     *        Email    :xxxxxxx
     *        Copyright:NEWPLAN
    -----------------------------------------------*/
    #include <iostream>
    
    #define MAXNUM 100            //最高次数
    
    unsigned  long ww[MAXNUM*11][MAXNUM*11];
    unsigned long dynamic_GetPartitionCount(int n, int max);
    
    using namespace std;
    
    int main(int argc, char **argv)
    {
        int n;
        int m;
        unsigned long count;
    	
    	while(1)
    	{
    		cin>>n;
    		cout<<dynamic_GetPartitionCount(n,n)<<endl;
    	}
    	
        return 0;
    }
    
    unsigned long dynamic_GetPartitionCount(int n, int max)
    {
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=i;j++)
    		{
    			if(j==1|| i==1)
    			{
    				ww[i][j]=1;
    			}
    			else 
    			{
    				if(j==i)
    					ww[i][j]=ww[i][j-1]+1;
    				else if((i-j)<j)
    					ww[i][j]=ww[i-j][i-j]+ww[i][j-1];
    				else
    					ww[i][j]=ww[i-j][j]+ww[i][j-1];
    			}
    		}
    	return ww[n][max];
    }
    

     

     

    三种方法效果对比十分明显,在写此博客之前测试数据200,动态规划版本输入直接算出结果,现在这片博客写完了,,,使用递归的还没计算出结果。。。


     

     

    方法三:母函数

     

        下面我们从另一个角度,即“母函数”的角度来考虑这个问题。

        所谓母函数,即为关于x的一个多项式G(x):

        有G(x) = a0 + a1*x + a2*x^2 + a3*x^3 + ......

        则我们称G(x)为序列(a0, a1, a2,.....)的母函数。关于母函数的思路我们不做更过分析。

        我们从整数划分考虑,假设n的某个划分中,1的出现个数记为a1,2的个数记为a2,.....,i的个数记为ai,

        显然有:ak <= n/k(0<= k <=n)

        因此n的划分数f(n,n),也就是从1到n这n个数字抽取这样的组合,每个数字理论上可以无限重复出现,即个数随意,使它们的综合为n。显然,数字i可以有如下可能,出现0次(即不出现),1次,2次,......,k次等等。把数字i用(x^i)表示,出现k次的数字i用(x^(i*k))表示,不出现用1表示。

        例如,数字2用x^2表示,2个2用x^4表示,3个2用x^6表示,k个2用x^2k表示。

        则对于从1到N的所有可能组合结果我们可以表示为:

        G(x) = ( 1 + x + x^2 + x^3 + ... + x^n)*(1 + x^2 + x^4 + x^6 + ....)....(1 + x^n)

                = g(x,1)*g(x,2)*g(x,3)*....*g(x,n)

                = a0 + a1*x + a2*x^2 +...+ an*x^n + ....//展开式

        上面的表达式中,每个括号内的多项式代表了数字i的参与到划分中的所有可能情况。因此,该多项式展开后,由于x^a *x^b = x^(a+b),因此x^i就代表了i的划分,展开后(x^i)项的系数也就是i的所有划分个数,即f(n,n) = an。

        由此我们找到了关于整数划分的母函数G(x);剩下的问题就是,我们需要求出G(x)的展开后的所有系数。

        为此,我们首先要做多项式乘法,对于我们来说,并不困难。我们把一个关于x的多项式用一个整数数组a[]表示,a[i]代表x^i的系数,即:

        g(x) = a[0] + a[1]x + a[2]x^2 + ... + a[n]x^n;

        则关于多项式乘法的代码如下,其中数组a和数组b表示两个要相乘的多项式,结果存储到数组c中。

    参考题目: HDU:1028:Ignatius and the Princess III

    参考源码:

     

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    
    using namespace std;
    
    const int N=10005;
    
    int c1[N],c2[N];
    
    int main()
    {
        int n,i,j,k;
        while(cin>>n)
        {
            if(n==0) break;
            for(i=0;i<=n;i++)
            {
                c1[i]=1;
                c2[i]=0;
            }
            for(i=2;i<=n;i++)
            {
                for(j=0;j<=n;j++)
                    for(k=0;k+j<=n;k+=i)
                        c2[k+j]+=c1[j];
                for(j=0;j<=n;j++)
                {
                    c1[j]=c2[j];
                    c2[j]=0;
                }
            }
            cout<<c1[n]<<endl;
        }
        return 0;
    }

     

     

     

     

     

    方法四:五边形数定理

     

    设第n个五边形数为,那么,即序列为:1, 5, 12, 22, 35, 51, 70, ... 

    对应图形如下:

     

    设五边形数的生成函数为,那么有:

    以上是五边形数的情况。下面是关于五边形数定理的内容:

    五边形数定理是一个由欧拉发现的数学定理,描述欧拉函数展开式的特性。欧拉函数的展开式如下:

    欧拉函数展开后,有些次方项被消去,只留下次方项为1, 2, 5, 7, 12, ...的项次,留下来的次方恰为广义五边形数。 

    五边形数和分割函数的关系

    欧拉函数的倒数是分割函数的母函数,亦即:

       其中为k的分割函数。

    上式配合五边形数定理,有:

     

    在 n>0 时,等式右侧的系数均为0,比较等式二侧的系数,可得

    p(n) - p(n-1) - p(n-2) + p(n-5) + p(n-7) + \cdots=0

    因此可得到分割函数p(n)的递归式:p(n) = p(n-1) + p(n-2) - p(n-5) - p(n-7) + \cdots

    例如n=10时,有:p(10) = p(9) + p(8) - p(5) - p(3) = 30 + 22 - 7 -  3 = 42

    所以,通过上面递归式,我们可以很快速地计算n的整数划分方案数p(n)了。

     

    参考例题:

    HUD4651:Partition

    源码:

     

    #include <iostream>
    
    using namespace std;
    
    #define  MYDATA long long
    const MYDATA MOD=1000000007;
    
    #define  AMS 100005
    MYDATA pp[AMS];
    MYDATA asist[2*AMS];
    void myinit()
    {
    	for(int i=0;i<AMS;i++)
    	{
    		/*算出五角数(正常五角数为1,5,12,22.... k*(3*k-1)/2)*/
    		/*此部分,需要算出的是分割函数(1,2,5,7,12,15,22,26.....
    		[k*(3*k-1)/2,k*(3*k+1)/2 ])*/
    		asist[2*i]=i*(i*3-1)/2;
    		asist[2*i+1]=i*(i*3+1)/2;
    	}
    }
    void mymethod()
    {
    	pp[1]=1;
    	pp[2]=2;
    	pp[0]=1;
    	for(int i=3;i<AMS;i++)
    	{
    		int k=0;
    		int flags;
    		pp[i]=0;
    		/*pp[n]=pp[n-1]+pp[n-2]-pp[n-5]-pp[n-7]+pp[12]+pp[15]
    		-.... ..... [+pp[n-k*[3k-1]/2]  + pp[n-k*[3k+1]/2]]*/
    		for(int j=2;asist[j]<=i;j++)
    		{
    			/*说明:式子中+MOD是必须的,否则输出可能出错(有可能为负数)*/
    			flags=k&2;
    			if(!flags)
    				pp[i]=(pp[i]+pp[i-asist[j]]+MOD)%MOD;
    			else
    				pp[i]=(pp[i]-pp[i-asist[j]]+MOD)%MOD;
    			k++;
    			k%=8;
    		}
    	}
    }
    
    int main()
    { 
    	int t,n;
    	myinit();
    	mymethod();
      
        cin>>t;
        while(t--)
        {
            cin>>n;
    	cout<<pp[n]<<endl;
        }
        return 0;
    }
    

     

    附加:

     

    给定一个整数n,输出这个整数拆分的可能形式(即输出全部情况)

    使用递归情况

    整个输出类似于一颗树,以分解6为例,过程如下图

     

     

    源码实现:

     

    #include <stdio.h>
    
    //使用一个数组记录在递归过程中产生的前面需要重复输出的值
    int set[100];
    //用于在递归过程中判断是否递归到最深处,输出回车
    int k;
    
    //此函数表示使用不大于m的整数对n进行拆分的情况,i用于表示set数组已经存在的记录数长度
    void q(int n,int m,int i)
    {
        if(n==k&&n!=m)
        {
            //此时递归栈已经退回到某一分支的最上层,输出回车
            //并重置计数器i为0
            printf("\n");
            i=0;
        }
        if(n==1)
        {
            //当n为1,意味者着只能表示1
            printf("1 ");
            return;
        }
        else if(m==1)
        {
            //当m为1,意味着要输出n个m相加
            for(int i=0; i<n-1; i++)
                printf("1+");
            printf("1 ");
            return;
        }
        if(n<m)
        {
            q(n,n,i);
        }
        if(n==m)
        {
            //当n等于m时,到达本次递归求和的一个叶子,此时需要输出多一个空格,表示下一次输出为另一个叶子
            printf("%d ",n);
            //在递归输出另一个叶子之前,将之前记录的在叶子之上的数一并输出,如上图示过程1
            for(int j=0; j<i; j++)
                printf("%d+",set[j]);
            q(n,m-1,i);
    
        }
        if(n>m)
        {
            //如果n大于m,使用m作为分解,则要首先输出m+的形式
            printf("%d+",m);
            //记录下作为树干节点m的值并使i自增
            set[i++]=m;
            //递归输出m+以后的分解
            q(n-m,m,i);
            //递归完毕后需要将数组记录后退一个,回到上一个节点,如上图示过程2
            i--;
            //执行另一个分支,在下一次递归之前输出记录的数据,如上图示过程3
            for(int j=0; j<i; j++)
                printf("%d+",set[j]);
            //递归输出另一分支情况
            q(n,m-1,i);
        }
    
    
    }
    
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            if(n<=0)
            {
                printf("Please input a positive interger.\n\n");
                continue;
            }
            k=n;
            q(n,n,0);
            printf("\n\n");
        }
        return 0;
    }
    

     

     

     

     

     

     

    展开全文
  • int型整数的范围

    2018-08-10 16:40:06
    计算机中32位int类型变量的范围,其中int类型是带符号整数。 正数在计算机中表示为原码,最高位为符号位: 1的原码为0000 0000 0000 0000 0000 0000 0000 0001 2147483647的原码为0111 1111 1111 1111 1111 1111 ...
  • 整数的分类处理

    2018-12-22 12:30:11
    整数的分类处理 (C语言) 给定 N 个正整数,要求你从中得到下列三种计算结果: A1 = 能被 3 整除的最大整数 A2 = 存在整数 K 使之可以表示为 3K+1 的整数的个数 A3 = 存在整数 K 使之可以表示为 3K+2 的所有整数的...
  • 自然数就是没有负数的整数,即0和正整数。(如0,1,2……)  整数就是没有小数位都是零的数 ,即能被1整除的数(如-1,-2,0,1,……)。  有理数是只有限位小数(可为零位)或是无限循环小数(如1,1.42,3.5,1/3,0....
  • 合数是指在大于1的整数中除了能被1和本身整除外,还能被其他数(0除外)整除的数。 质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数 (2)解题思路 本题中数字2...
  • #include<stdio.h> int main() { int n,i; printf("Plz input int:"); scanf("%d",&n); printf("%d=",n); for(i=2;i<=n;i++) { whil...
  • 把一个正整数m分成n个正整数的和,有多少种分法? 例:把5分成3个正正数的和,有两种分法: 1 1 3 1 2 2 输入第一行是一个整数T表示共有T组测试数据(T 每组测试数据都是两个正整数m,n,其中(1
  • 分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!... * 题目: 输入一个正整数n,输出所有和为n的连续正整数序列。例如:输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5、4-6...
  • 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。 示例 1: 输入: 123 输出: 321 示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出: 21 注意: 假设我们的环境只能存储得下 32 位的有符号...
  • 请你来实现一个 atoi 函数,使其能将字符串转换成整数。 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽...
  • Java进阶(五十二)两个整数相除得到小数点并保留两位小数的方法  当两个整数相除时,由于小数点以后的数字会被截断,使运算结果为整数,故此时若希望得到运算结果为所预期的浮点数,则此时必须将两整数其一或是全部...
  • C++ - 整数反转

    2019-03-13 22:36:17
    分享一个大牛的人工智能教程。零基础!通俗易懂!... * 题目很简单,完成函数reverse,实现把给定的一个整数反转。 * 举两个例子如下:x = 123,return 321;x = -123,return -321。 */ #in...
  • 由用户输入一个正整数n,分析出该正整数的每一位,然后将各位数字从大到小重新排序后得到正整数m,输出m和n的平均值。 (1)编写输出正整数n和m的程序。 (2)给出调试过的输出m和n的平均值的源程序。 #include <...
  • 正数的正则表达式(包括0,小数保留两位):^((0{1}\.\d{1,2})|([1-9]\d*\.{1}\d{1,2})|([1-9]+\d*)|0)$ 正数的正则表达式(不包括0,小数保留两位):^((0{1}\... 正整数的正则表达式(包括0):^[+]{0,1}(\d+)$ 正整...
  • 计算若干整数的和,这些整数都是小于1000的非负整数。 Input 输入为多行,每行为一组测试样例。每个测试样例以一个整数N开始,后面接着是N个整数。当输入的N为0时表示输入结束。 Output 每组测试样例对应一行输出,...
  • C语言大整数加法

    2019-03-21 12:30:55
    C语言实现大整数加法 题目描述: 1:大整数加法 总时间限制: 1000ms 内存限制: 65536kB 描述 求两个不超过200位的非负整数的和。 输入 有两行,每行是一个不超过200位的非负整数,可能有多余的前导0。 输出 一行,即...
  • 标题以下程序从读入的整数数据中,统计大于零的整数个数和小于零的整数个数。用输入零来结束输入,程序中用i统计大于零的个数,用变量j统计小于零的整数。 在这里插入代码片 #include<stdio.h> int main() { ...
1 2 3 4 5 ... 20
收藏数 2,038,710
精华内容 815,484
关键字:

整数