当小球遇上盒子

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/strangeDDDF/article/details/88319108

小球与盒子问题

  • 这类问题是求解把一些小球放进一些盒子里的本质不同的方案数。
  • 通过球相同/不同,盒子相同/不同,能/不能有空盒分成了8个不同的问题。
  • 本篇文章会分别对这8个问题进行分析求解。

前置芝士&复习巩固

  • 组合数 :从nn个物品里选出m个物品进行组合的方案数。
    Cnm=n!m!(nm)!C_{n}^{m}=\frac{n!}{m!\cdot (n-m)!}

  • 排列数 :从nn个物品里选出mm个物品进行排列的方案数。
    Anm=n!(nm)!A_{n}^{m}=\frac{n!}{(n-m)!}

  • 圆排列:一个nn个元素构成的集合,从中选出mm个元素构成一个环的方案数。
    Qnm=AnmmQ_{n}^{m}=\frac{A_{n}^{m}}{m}

  • 第一类斯特林数:用nn个元素组成mm个环的方案数。
    snm=sn1m1+(n1)sn1ms_{n}^{m}=s_{n-1}^{m-1}+(n-1)\cdot s_{n-1}^{m}

  • 第二类斯特林数:把一个大小为nn的集合划分成mm个非空集合的方案数,集合内部无序。
    Snm=Sn1m1+mSn1mS_{n}^{m}=S_{n-1}^{m-1}+m\cdot S_{n-1}^{m}

1.球相同,盒子不同,不能有空盒

  • 就是把nn个球分成mm份,每一份不能为空,插m1m-1个板即可。
    ans=Cn1m1ans=C_{n-1}^{m-1}

2.球相同,盒子不同,可以有空盒

  • 把n个球分成mm份,每一份可以为空,再增加mm个球,插m1m-1个板,每一份再拿走一个球即可。
    ans=Cn+m1m1ans=C_{n+m-1}^{m-1}

3.球不同,盒子不同,可以有空盒

  • 对于每一个球,你都可以放到[1,m][1,m]的任意一个位置,由于球不同,所以球与球之间是独立的。
    ans=mnans=m^{n}

4.球不同,盒子不同,不能有空盒

  • 对空着的位置进行容斥
  • f[i]f[i]表示至少有i个空盒的方案数,ans[i]ans[i]表示有i个空盒的方案数
    f[i]=(mi)nCmif[i]=(m-i)^{n}\cdot C_{m}^{i}
    f[i]=j=imCjians[j]f[i]=\sum_{j=i}^{m}C_{j}^{i}\cdot ans[j]
  • 二项式反演可得
    ans[i]=j=im(1)j+iCjif[j]ans[i]=\sum_{j=i}^{m}(-1)^{j+i}C_{j}^{i}\cdot f[j]
  • 最后答案就是ans[0]ans[0],即
    i=0m(1)if[i]\sum_{i=0}^{m}(-1)^{i}f[i]

5.球不同,盒子相同,不能有空盒

  • 相当于把n个元素的集合划分成mm份,也就是第二类斯特林数
    ans=Snmans=S_{n}^{m}

  • 这个做法时间复杂度是O(n2)O(n^{2})

  • 其实这个就是问题4的答案除以m!m!,可以用问题4的容斥

6.球不同,盒子相同,可以有空盒

  • 因为可以有空盒,我们可以枚举每次一共用了几个盒子,然后把相应的第二类斯特林数加起来就可以了
    ans=i=0mS[n][i]ans=\sum_{i=0}^{m}S[n][i]
  • 这种数也叫BellBell
  • BellBell数的定义:第nnBellBell数表示集合[1,2,3,...,n][1,2,3,...,n]的划分方案数
    Bn=m=0nS[n][m]B_{n}=\sum_{m=0}^{n}S[n][m]

7.球相同,盒子相同,可以有空盒

  • f[n][m]f[n][m]表示nn个球放到mm个盒子里的方案数
    if(n==0m==1)      f[n][m]=1if(n==0||m==1)~~~~~~f[n][m]=1
    if(n<m)      f[n][m]=f[n][n]if(n<m)~~~~~~f[n][m]=f[n][n]
    if(n>=m)      f[n][m]=f[nm][m]+f[n][m1]if(n>=m)~~~~~~f[n][m]=f[n-m][m]+f[n][m-1]
  • 如果球比盒子多,分为放满和不放满两种情况讨论
  • 等价于自然数拆分问题

8.球相同,盒子相同,不能有空盒

  • 我们首先在所有的盒子中放一个球,就转化成了问题7
    ans=f[nm][m]ans=f[n-m][m]

以上就是盒子小球最基础的八种情况了

盒子与小球二

  • NN个有差别的盒子(1<=N<=20)(1<=N<=20)。你有AA个红球和BB个蓝球。0<=A<=15,0<=B<=150 <= A <= 15, 0 <= B <= 15。球除了颜色没有任何区别。你可以将球放进盒子。一个盒子可以同时放进两种球,也可以只放一种,也可以空着。球不必全部放入盒子中。编程计算有多少种放置球的方法。
  • AA的放置和BB的放置互不影响,所以我们可以单独计算方案,最后相乘即可
  • 枚举球放了ii个,放满了jj个盒子里
    ansA=1+i=1Aj=1min(i,n)CnjCi1j1ansA=1+\sum_{i=1}^{A}\sum_{j=1}^{min(i,n)}C_{n}^{j}\cdot C_{i-1}^{j-1}
    ansB=1+i=1Bj=1min(i,n)CnjCi1j1ansB=1+\sum_{i=1}^{B}\sum_{j=1}^{min(i,n)}C_{n}^{j}\cdot C_{i-1}^{j-1}
    ans=ansAansBans=ansA\cdot ansB

盒子与小球三

  • nn个相同的球,mm个不同的盒子,每个盒子最多放kk个球 ,请计算将这nn个球全部放入盒子中的方案数模10000071000007后的结果 ,n<=5000n<=5000m<=5000m<=5000
  • 对限制进行容斥
  • f[i]f[i]表示至少有i个盒子放的球大于kk个的方案数
    f[i]=CmiCni(k+1)+m1m1f[i]=C_{m}^{i}C_{n-i*(k+1)+m-1}^{m-1}
  • ans[i]ans[i]表示有i个盒子放的球大于k个的方案数
    ans[i]=j=im(1)j+if[j]ans[i]=\sum_{j=i}^{m}(-1)^{j+i}\cdot f[j]
  • 答案就是ans[0]ans[0],即
    i=0m(1)iCmiCni(k+1)+m1m1\sum_{i=0}^{m}(-1)^{i}\cdot C_{m}^{i}C_{n-i*(k+1)+m-1}^{m-1}

盒子与小球四

  • 给定nn个各不相同的小球,和mm个不同的BOXBOX,有多少种不同的放球方法,使得每个BOXBOX里的小球个数不小于kkn,m,k<=15n,m,k<=15
  • f[i][j]f[i][j]表示前i个盒子放了j个球的方案数
    f[i][j]=l=kjf[i1][jl]Cn(jl)lf[i][j]=\sum_{l=k}^{j}f[i-1][j-l]\cdot C_{n-(j-l)}^{l}

完结撒花

展开阅读全文

当GPL遇上MP

01-25

[align=center]当GPL遇上MP[/align]rnrn[align=center]莫华枫[/align]rnrn GPL,也就是General Purpose Language,是我们使用的最多的一类语言。传统上,GPL的语法,或者特性,是固态的。然而,程序员都是聪明人(即便算不上“最聪明”,也算得上 “很聪明”吧:)),往往不愿受到语法的束缚,试图按自己的心意“改造”语言。实际上,即便是早期的语言,也提供了一些工具,供聪明人们玩弄语法。我看的第一本C语言的书里,就有这么一个例子,展示出这种“邪恶”的手段:rn #define procedure voidrn #define begin rn #define end rn 然后:rn procedure fun(int x)rn beginrn ...rn endrn 实际上,它的意思是:rn void fun(int x)rn rn ...rn rn 这可以看作是对初学C语言的Pascal程序员的安慰。这种蹩脚的戏法可以算作元编程的一种,在一种语言里创造了另一个语法。不过,实在有些无聊。然而,在实际开发中,我们或多或少地会需要一些超出语法范围的机制。有时为了完善语言,弥补一些缺憾;有时为了增强一些功能;有时为了获得一些方便。更新潮的,是试图在一种GPL里构建Domain Specific Language,或者说“子语言”,以获得某个特性领域上更直观、更简洁的编程方式。这些对语言的扩展需求的实现,依赖于被称为Meta- Programming(MP)的技术。rn 另一方面,随着语言功能和特性的不断增加,越来越多的人开始抱怨语言太复杂。一方面:“难道我们会需要那些一辈子也用不到几回的语言机制,来增加语言的复杂性和学习使用者的负担吗?”。另一方面:“有备无患,一个语言机制要到迫在眉睫的时候才去考虑吗?”。但MP技术则将这对矛盾消弭于无形。一种语言,可以简洁到只需最基本的一些特性。而其他特定的语言功能需求,可以通过MP加以扩展。如果不需要某种特性,那么只要不加载相应的MP代码即可,而无需为那些机制而烦恼。rn MP最诱人的地方,莫过于我们可以通过编写一个代码库便使得语言具备以往没有的特性。rn 然而,全面的MP能力往往带来巨大的副作用,以至于我们无法知道到底是好处更多,还是副作用更多。语言的随意扩展往往带来某些危险,比如语法的冲突和不兼容,对基础语言的干扰,关键字的泛滥等等。换句话说,MP是孙悟空,本领高强。但没有紧箍咒,是管不住他的。rn 那么,紧箍咒是什么呢?这就是这里打算探讨的主题。本文打算通过观察两种已存在的MP技术,分析它们的特点与缺陷,从中找出解决问题的(可能)途径。rnrn[size=16px]AST宏[/size]rn 首先,先来看一下宏,这种远古时代遗留下来的技术。以及它的后裔,ast宏。rn 关于传统的宏的MP功能,上面的代码已经简单地展示了。但是,这种功能是极其有限的。宏是通过文本替换的形式,把语言中的一些符号、操作符、关键字等等替换成另一种形式。而对于复杂的语法构造的创建无能为力。问题的另一面,宏带来了很多副作用。由于宏的基础是文本替换,所以几乎不受语法和语义的约束。而且,宏的调试困难,通常也不受命名空间的约束。它带来的麻烦,往往多于带来的好处。rn ast宏作为传统宏的后继者,做了改进,使得宏可以在ast(Abstract Syntax Tree)结构上执行语法的匹配。(这里需要感谢TopLanguage上的Olerev兄,他用简洁而又清晰的文字,对我进行了ast宏的初级培训:))。这样,便可以创造新的语法:rn syntax(x, "<->", y, ";")rn rn std::swap(x, y);rn rn 当遇到代码:rn x <-> y;rn 的时候,编译器用std::swap(x,y);加以替换。实际上,这是将一种语法结构映射到另一个语法结构上。而ast宏则是这种映射的执行者。rn 但是,ast宏并未消除宏本身的那些缺陷。如果x或者y本身不符合swap的要求(类型相同,并且能复制构造和赋值,或者拥有swap成员函数),那么 ast宏调用的时候无法对此作出检验。宏通常以预编译器处理,ast宏则将其推迟到语法分析之时。但是此时依然无法得到x或y的语义特征,无法直接在调用点给出错误信息。rn 同时,ast宏还是无法处理二义性的语法构造。如果一个ast宏所定义的语法构造与主语言,或者其他ast宏的相同,则会引发混乱。但是,如果简单粗暴地将这种“重定义”作为非法处理,那么会大大缩小ast宏(以及MP)的应用范围。实际上,这种语法构造的重定义有其现实意义,可以看作一种语法构造的“重载”,或者函数(操作符)重载的一种扩展。rn 解决的方法并不复杂,就是为ast宏加上约束。实际上,类似的情形在C++98的模板上也存在,而C++则试图通过为模板添加concept约束加以解决。这种约束有两个作用:其一,在第一时间对ast宏的使用进行正确性检验,而无需等到代码展开之后;其二,用以区分同一个语法构造的不同版本。rn 于是,对于上述例子可以这样施加约束(这些代码只能表达一个意思,还无法看作真正意义上的MP语法):rn syntax(x, "<->", y, ";")rn where x,y is object of concept (has_swap_mem or (CopyConstructable and Assignable))rn && typeof(x)==typeof(y)rn rn std::swap(x,y);rn rn 如此,除非x,y都是对象,并且符合所指定的concept,否则编译器会当即加以拒绝,而且直截了当。rn 不过,如此变化之后,ast宏将不会再是宏了。因为这种约束是语义上的,必须等到语义分析阶段,方能检验。这就超出了宏的领地了。不过既然ast宏可以从预处理阶段推迟到语法分析阶段,那么再推迟一下也没关系。再说,我们关注的是这种功能,带约束的ast宏到底是不是宏,也无关紧要。rnrn[size=16px]TMP[/size]rn 下面,我们回过头,再来看看另一种MP技术——TMP(参考David Abrahams, Aleksey Gurtovoy所著的《C++ Template Metaprogramming》)。对于TMP存在颇多争议,支持者认为它提供了更多的功能和灵活性;反对者认为TMP过于tricky,难于运用和调试。不管怎么样,TMP的出现向我们展示了一种可能性,即在GPL中安全地进行MP编程的可能性。由于TMP所运用的都是C++本身的语言机制,而这些机制都是相容的。所以,TMP所构建的 MP体系不会同GPL和其他子语言的语法机制相冲突。rn 实际上,TMP依赖于C++的模板及其特化机制所构建的编译期计算体系,以及操作符的重载和模板化。下面的代码摘自boost::spirit的文档:rn group = '(' >> expr >> ')';rnrn expr1 = integer | group;rnrn expr2 = expr1 >> *(('*' >> expr1) | ('/' >> expr1));rnrn expr = expr2 >> *(('+' >> expr2) | ('-' >> expr2));rnrn 这里表达了一组EBNF(语法着实古怪,这咱待会儿再说):>>代表了标准EBNF的“followed by”,*代表了标准EBNF的*(从右边移到左边),括号还是括号,|依旧表示Union。通过对这些操作符的重载,赋予了它们新的语义(即EBNF的相关语义)。然后配合模板的类型推导、特化等等机制,变戏法般地构造出一个语法解析器,而且是编译时完成的。rnrn 尽管在spirit中,>>、*、|等操作符被挪作他用,但是我们依然可以在这些代码的前后左右插入诸如:cin>> *ptrX;的代码,而不会引发任何问题。这是因为>>等操作符是按照不同的类型重载的,对于不同类型的对象的调用,会调用不同版本的操作符重载,互不干扰,老少无欺。rnrn 但是,TMP存在两个问题。其一,错误处理不足。如果我不小心把第二行代码错写成:expr1 = i | group;,而i是一个int类型的变量,那么编译器往往会给出一些稀奇古怪的错误。无非就是说类型不匹配之类的,但是很晦涩。这方面也是TMP受人诟病的一个主要原因。好在C++0x中的concept可以对模板作出约束,并且在调用点直接给出错误提示。随着这些技术的引入,这方面问题将会得到缓解。rnrn 其二,受到C++语法体系的约束,MP无法自由地按我们习惯的形式定义语法构造。前面说过了,spirit的EBNF语法与标准EBNF有不小的差异,这对于spirit的使用造成了不便。同样,如果试图运用TMP在C++中构造更高级的DSL应用,诸如一种用于记账的帐务处理语言,将会遇到更大的限制。实际上TMP下的DSL也很少有令人满意的。rnrn 所以说,TMP在使用上的安全性来源于操作符复用(或重载)的特性。但是,操作符本身的语法特性是固定的,这使得依赖于操作符(泛化或非泛化)重载的TMP不可能成为真正意义上的MP手段。rnrn 那么,对于TMP而言,我们感兴趣的是它的安全性和相容性。而对其不满的,则是语法构造的灵活性。本着“去其糟粕,取其精华”的宗旨,我们可以对TMP做一番改进,以获得更完整的MP技术。TMP的核心自然是模板(类模板和函数/操作符模板),在concept的帮助下,模板可以获得最好的安全性和相容性。以此为基础,如果我们将模板扩展到语法构造上,那么便可以在保留TMP的安全性和相容性的情况下,获得更大的语法灵活性。也就是说,我们需要增加一种模板——语法模板:rnrn templatern syntax synSwap=x "<->" y ";"rn require SameType && (has_swap_mem || (CopyConstructable and Assignable)rn rn std::swap(x, y);rn rnrn 这里我杜撰了关键字syntax,并且允许为语法构造命名,便于使用。而语法构造描述,则是等号后面的部分。require沿用自C++0x的concept提案。稍作了些改造,允许concept之间的||。 论坛

当移动遇上

07-02

近年来,在网络技术更新、数据业务种类不断丰富,以及智能终端迅速普及的推动下,网络流量长期呈现高速增长的态势,为应对这一挑战,运营商不断地扩容网络,但由于数据类业务的经营者大多数情况下不是运营商而是内容提供商,导致网络投资增长与营收增长形成越来越大的剪刀差。rnrn流量仍将维持高速增长已成为业界共识,要避免剪刀差日益扩大,须考虑如何降低网络投资的增速,可喜的是,我们已经能够看到实现这一目标所需的技术日渐成熟,这其中包括了目前广受关注的几个领域,即NFV(网络功能虚拟化)、SDN(软件定义网络)和云计算。rnrn相对于固网而言,移动网络的投资增速更加显著,移动运营商对降低投资增速的需求也更加迫切,在全球范围,移动运营商已开始在网络的各个层面引入新技术以实现上述目的。包括在RAN部分实施云化提升网络利用率;在分组核心和IMS引入NFV,降低对私有硬件的依赖并减少投资;在DC和承载网引入SDN,提升网络利用率和灵活性等。rnrn移动云网络引领新浪潮rnrn在2014年MWC期间,中国移动联手阿尔卡特朗讯展示了NFV领域的研发进展。在多厂商环境下,采用阿尔卡特朗讯基于概念验证的LTE RAN虚拟化BBU和虚拟分组核心演进vEPC解决方案,两家公司成功展示了开放性移动云网络在增强网络敏捷性、效率性和规模方面的效用。此外,还展示了vEPC、vIMS、vRAN产品,其中利用软件作为基础的vEPC,其效能已经在全球最大的两个LTE网络上得到验证,公司目前正在与5家运营商开展vEPC的相关研究与试/商用。rnrn作为IP网络和超宽带接入专家,阿尔卡特朗讯帮助包括中国移动在内的客户解决在其网络上面临的问题,全力投入开放性的运营商级虚拟化解决方案的研究。rnrn中国移动研究院首席科学家易芝玲博士表示:“长期以来,中国移动和上海贝尔强强联合以提供创新的解决方案,推动电信技术不断向前发展,本次在NFV领域的合作也是其中的一部分。此次我们成功展示了云网络环境在帮助更多客户提供更快、更好服务方面的重要作用。这将帮助我们满足移动数据需求的爆炸式增长,并促进我们进一步创新,推出新的服务产品。”rnrnCloudband+Nuage SDN=强健云平台rnrn这些虚拟化产品都在阿尔卡特朗讯的Cloudband2.0 NFV平台中承载和管理。Cloudband 2.0版本扩展后已经能够支持更强的网络控制、更广泛的开放式行业标准技术和虚拟网络功能。它还集成了阿尔卡特朗讯的SDN投资公司Nuage Networks的虚拟服务平台(VSP)。Nuage Networks公司的软件定义网络(SDN)解决方案提供高度自动化的、可编程和快速反应的网络,能够在云时代里支持IT和电信应用。rnrn通过一个简单的场景,即可了解Cloudband与Nuage SDN是如何协同工作,并支持NFV的(如图)。首先,运维人员将MME扩容指令由5620 SAM网管发出;由于vMME建构于Cloudband平台,因此该需求将送至Cloudband管理系统,在Cloudband平台中,提供众多的XaaS功能,大部分的NFV功能将使用cPaaS(Carrier-PaaS)提供,与MME对应的为vMME cPaaS,cPaaS使用预先创建的扩容脚本来创建虚机,该脚本定义了虚机的具体配置及承载的MME功能属性;当新的vMME虚机创建成功后,下一步就要将其加入vMME Pool-承载Cloudband Node的Nuage SDN可检测到新的虚机生成,并知晓其MME特征,据此创建新的vMME虚机与原vMME Pool的连接;加入后,vMME将向5620 SAM回送操作结果。rnrnCloudbandrnrnCloudband方案提供一个运营商级别的架构来建立和管理一个运营商云服务的发布环境。rnrn作为Cloudband管理系统的一部分,Carrier PaaS帮助运营商完成在云平台上的应用部署,实现对电信应用生命周期的管理,并充分利用云平台开放的全部能力创建一个开放的,有弹性的,自动化的,多租户和自我服务为导向的运营商级PaaS环境。rnrnCarrier PaaS位于云计算IaaS平台之上,使用IaaS平台所提供的北向API。从层次结构上来看,Carrier PaaS是一个基于IaaS平台接口之上的一个中间件环境,通常它与IaaS平台的管理系统以紧耦合的形式集成在一起,但它的独立性较好,也可以从管理系统中拆分出来独立运行,避免由于Carrier PaaS层的出现错误而导致管理系统内其他模块受到影响。Carrier PaaS将IaaS和PaaS平台所提供的各类API进行聚类和整合,提供给应用开发者和应用运维部门使用。rnrnNuage SDNrnrnNuage SDN解决方案虚拟化业务平台(VSP)是一个完整的多用户云数据中心网络服务解决方案,由三部分组成:VSD、VSC、VRS,分别负责策略,集中控制和虚拟路由交换。通过这三个关键部件,Nuage VSP全面介入数据中心网络的服务平面,控制平面和转发平面。rnrn在一个使用了阿尔卡特朗讯SDN解决方案的云服务架构中,管理员如果想创建和交付一个新的云服务,可方便地按照应用的需求进行网络服务设计。rnrnNuage SDN检测并响应虚拟机的创建和释放,并自动地按照既定的策略调整网络服务。无缝配合虚拟机的迁移,不受边界限制(如机架、集群、区域等)。消除那些人为界限,使网络服务可以在数据中心内甚至跨越多个数据中心间移动。rnrn目前,阿尔卡特朗讯已签署了5个关于提供Nuage Networks SDN解决方案的合同。rnrn尤为值得一提的是,除了在移动分组核心网推进虚拟化,阿尔卡特朗讯还在IMS中积极引入NFV ——目前已经将PCRF、HSS等功能迁移至Cloudband平台,通过采用全新的开放性云技术,可以使其在100%负荷的最大规模通信网络中规模运行时仍保持高性能状态。阿尔卡特朗讯的vIMS已经在现网部署,并且正与8家vIMS云客户进行测试。rnrn在承载网方面,阿尔卡特朗讯已成功实现RR(Route Reflector)的虚拟化,此前,RR基于专有的路由器硬件平台,其特点为计算、查询密集,但并不涉及转发等动作。在某些网络上,为应对高密度的RR需求,甚至独立部署一台高性能路由器来完成此工作,这同时也浪费了路由器的核心价值。通过将RR部署至云平台,可充分利用其计算优势,并可随需伸缩。rnrn阿尔卡特朗讯致力于加快行业NFV的部署,目前正服务于3个Cloudband NFV客户合同以及10个试验项目,积极参与ETSI NFV咨询委员会和设立Cloudband生态系统计划,并帮助中国运营商有序、平稳地推进移动网络云化。rn 论坛

没有更多推荐了,返回首页