• 母函数


                          

    有1克、2克、3克、4克的砝码各一枚,能称出哪几种重量?每种重量各有几种可能方案? 

    考虑用母函数来接吻这个问题:

    我们假设x表示砝码,x的指数表示砝码的重量,这样:

    1个1克的砝码可以用函数1+x表示,

    1个2克的砝码可以用函数1+x2表示,

    1个3克的砝码可以用函数1+x3表示,

    1个4克的砝码可以用函数1+x4表示,

    几种砝码的组合可以称重的情况,可以用以上几个函数的乘积表示:

    (1+x)(1+x2)(1+x3)(1+x4)

    =(1+x+x2+x3)(1+x3+x4+x7)

    =1+x+x2+2x3+2x4+2x5+2x6+2x7+x8+x9+x10 

    从上面的函数知道:可称出从110,系数便是方案数。(!!!经典!!!)

        例如右端有2x5 项,即称出5克的方案有2:5=3+2=4+1;同样,6=1+2+3=4+2;10=1+2+3+4。

    1. 整数拆分

    输入一个整数n,把它拆成若干个整数相加,输出有多少种拆分的方法。

    比如:4=3+1=2+2=2+1+1=1+1+1+1,有5种。

    解:

    所谓整数拆分即把整数分解成若干整数的和(相当于把n个无区别的球放到n个无标志的盒子,盒子允许空,也允许放多于一个球)。

    G(x)=(1+x+x^2+…)(1+x^2+x^4+…)(1+x^3+x^6+…)…

    #include <stdio.h>

    #include <string.h>

    int main()

    {

        int c1[200],c2[200];     //c1保存当前表达式里各项的系数,c2是中间量

        int n,i,j,k;

        while(scanf("%d",&n)!=EOF)  

        {

            for(i=0;i<=n;i++)   //n拆分的数必定小于或等于n,所以只用从0遍历到n,即母函数的第1个括号里的表达式只能是1+x+x^2+…+x^n

            {

                c1[i]=1;          //初始化c1[],c1[]的下标是项的指数,值是项的系数

                c2[i]=0;

            }

            for(i=2;i<=n;i++)       //后面有n-1个表达式(括号里的式子),要展开n-1次,i指第i个表达式

            {

                for(j=0;j<=n;j++)

                {

                    for (k=0;k+j<=n;k=k+i)

                    {

                        c2[k+j]+=c1[j];        //只用保留指数<=n的项,所以k+j<=n

                    }                        //j指当前表达式里项的第j个项,k指后一个表达式里项的指数,k=k+i

                }                            //两个相邻表达式展开

                for(j=0;j<=n;j++)

                {

                    c1[j]=c2[j];

                    c2[j]=0;

                }            //每展开一次,就将c1[]更新,c2[]归0

            }

            printf("%d\n",c1[n]);

        }

        return 0;

    }

    1. 钱币组合:

    有面值为1,2,5的3种硬币,输入各硬币的个数,求最小的一个不能组合的成的价值。

    比如输入1 1 3,输出4

    解:

    G(x)=(1+x+x^2+…)(1+x^2+x^4+…)(1+x^5+x^10+…)

    3种面值,所以只有3个括号表达式。

    #include <stdio.h>
    #include <string.h>
    int main()
    {
        int a,b,c,i,j,k,sum;
        int c1[8008],c2[8008];
        int elem[3]={1,2,5};
        int num[4];
        while(scanf("%d%d%d",&a,&b,&c)!=EOF)
        {
            if(a==0&&b==0&&c==0)
                break;
            sum=1*a+2*b+5*c;
            num[1]=a;
            num[2]=b;
            num[3]=c;     //num[]存放括号内表达式的项的个数
     
            memset(c1,0,sizeof(c1));
            memset(c2,0,sizeof(c2));     //c1[],c2[]全部归0
            for(i=0;i<=a;i=i+elem[0])    //初始化第1个表达式里各项的系数
                c1[i]=1;
        
            for(i=2;i<=3;i++)
            {
                for(j=0;j<=sum;j++)
                {
                    for(k=0;k<=num[i]*elem[i-1]&&k+j<=sum;k=k+elem[i-1])
                    {
                        c2[j+k]+=c1[j];
                    }
                }
                for(j=0;j<=sum+1;j++)
                {
                    c1[j]=c2[j];
                    c2[j]=0;
                }
            }
            
            for(i=0;i<=sum+1;i++)
            {
                if(c1[i]==0)
                {
                    printf("%d\n",i);
                    break;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    PLC衔接新方式UcAsp.Opc
    dev barmanager 中的 add按钮出不来,无法创建菜单的问题解决
    一个或多个页边距被设置到也可打印的页面范围之外,处理方式
    bar设置全背景色
    PHP计算两个字符的相似程度similar_text
    PHP中双冒号::的用法
    百度站内搜索应该注意哪些方面?
    快给你的网站添加微信公众号吧!
    实例讲解网站前台界面开发流程
    百度富文本编辑器UEditor安装配置全过程
  • 原文地址:https://www.cnblogs.com/chiry/p/3225849.html
Copyright © 2020-2023  润新知