精华内容
下载资源
问答
  • 2020-10-16 20:55:30



    参考博客 :





    一、排列组合示例 1 ( 组合 | 乘法法则 | 加法法则 )



    基本计数公式就是 加法法则 , 乘法法则 ;


    1 1 1 ~ 300 300 300 中任意取出 3 3 3 个数 , 使得这三个数的和能被 3 3 3 整除 , 有多少种选取方法 ?


    使用 分类 ( 乘法法则 ) , 分布 ( 加法法则 ) , 排列组合 的方法进行解决 ;


    将上述 1 1 1 ~ 300 300 300 数字 , 按照除以 3 3 3 的余数分为以下三类 :

    • ① 除以 3 3 3 余数为 1 1 1 : A = { 1 , 4 , ⋯   , 298 } A = \{ 1, 4, \cdots , 298 \} A={1,4,,298}
    • ② 除以 3 3 3 余数为 2 2 2 : B = { 2 , 5 , ⋯   , 299 } B = \{ 2, 5, \cdots , 299 \} B={2,5,,299}
    • ③ 除以 3 3 3 余数为 0 0 0 : C = { 3 , 6 , ⋯   , 300 } C = \{ 3, 6, \cdots , 300\} C={3,6,,300}

    组合问题 :

    • A A A 集合中任选 3 3 3 个数 , 三个数之和肯定是 3 3 3 的倍数 , 可以倍 3 3 3 整除 ; 选取方法有 C ( 100 , 3 ) C(100, 3) C(100,3) 种 ;

    • B B B 集合中任选 3 3 3 个数 , 三个数之和肯定是 3 3 3 的倍数 , 可以倍 3 3 3 整除 ; 选取方法有 C ( 100 , 3 ) C(100, 3) C(100,3) 种 ;

    • C C C 集合中任选 3 3 3 个数 , 三个数之和肯定是 3 3 3 的倍数 , 可以倍 3 3 3 整除 ; 选取方法有 C ( 100 , 3 ) C(100, 3) C(100,3) 种 ;


    乘法法则 : A , B , C A,B,C A,B,C 中每个集合各取一个数 , 三个数之和也是 3 3 3 的倍数 ,

    • 第一个集合取 1 1 1 个数 , 100 100 100 种取法
    • 第二个集合取 1 1 1 个数 , 100 100 100 种取法
    • 第三个集合取 1 1 1 个数 , 100 100 100 种取法

    总共有 10 0 3 100^3 1003 种取法 ;



    最终的取法 , 使用加法法则 :

    3 C ( 100 , 3 ) + 10 0 3 = 1485100 3C(100, 3) + 100^3 = 1485100 3C(100,3)+1003=1485100





    二、排列组合示例 2



    1000 ! 1000! 1000! 末尾 0 0 0 的个数 ?


    这个数值使用乘法计算 , 非常大 , 基本无法计算 ;


    列出因式 : 1000 ! 1000! 1000! 看做

    1000 × 999 × 998 × ⋯ × 2 × 1 1000 \times 999 \times 998 \times \cdots \times 2 \times 1 1000×999×998××2×1

    因式 ;


    原理说明 : 上述因式中有 1000 1000 1000 个因子 , 将这 1000 1000 1000 个因子分解 , 如果分解式中有 i i i 5 5 5 , j j j 2 2 2 , 则 i i i j j j 中较小的值 min ⁡ { i , j } \min\{ i,j \} min{i,j} 就是 0 0 0 的个数 ;


    上述 1 1 1 ~ 1000 1000 1000 1000 1000 1000 个数字中统计分解出的 2 2 2 5 5 5 的个数


    统计 2 2 2 的因子个数 : 肯定大于 500 ;

    • ① 是 2 2 2 的倍数的数字有 500 500 500
    • ② 是 4 4 4 的倍数的数字有 250 250 250 , 分解出 2 × 2 2\times2 2×2 , 其中一个 2 2 2 在之前已经统计过 , 这里在加上 250 250 250 2 2 2 , 当前有 750 750 750 2 2 2 ;
    • ③ 是 16 16 16 的倍数的数字有 62 62 62 , 分解出 2 × 2 × 2 2\times2 \times 2 2×2×2 , 其中两个 2 2 2 在之前已经统计过 , 这里在加上 62 62 62 2 2 2 , 当前有 812 812 812 2 2 2 ;
    • ④ 是 32 32 32 的倍数的数字有 31 31 31 , 分解出 2 × 2 × 2 × 2 2\times2 \times 2\times 2 2×2×2×2 , 其中三个 2 2 2 在之前已经统计过 , 这里在加上 31 31 31 2 2 2 , 当前有 833 833 833 2 2 2 ;
      ⋮ \vdots

    统计 5 5 5 的因子个数 : 249 249 249 个 ;

    • ① 是 5 5 5 的倍数的数字有 200 200 200 , 统计有 1 1 1 个因子 5 5 5 的情况 , 其中肯定有的因子可以分解出 25 , 125 , 625 25, 125, 625 25,125,625 等情况 , 下面逐渐细化剥离出没有统计的因子 ;
    • ② 是 25 25 25 的倍数的数字有 40 40 40 , 分解出 5 × 5 5\times5 5×5 , 其中一个 5 5 5 在之前已经统计过 , 这里在加上 40 40 40 5 5 5 , 当前有 240 240 240 5 5 5 ;
    • ③ 是 125 125 125 的倍数的数字有 8 8 8 , 分解出 5 × 5 × 5 5\times5 \times 5 5×5×5 , 其中两个 5 5 5 在之前已经统计过 , 这里在加上 8 8 8 5 5 5 , 当前有 248 248 248 5 5 5 ;
    • ④ 是 625 625 625 的倍数的数字有 1 1 1 , 分解出 5 × 5 × 5 × 5 5\times5 \times 5 \times 5 5×5×5×5 , 其中三个 5 5 5 在之前已经统计过 , 这里在加上 1 1 1 5 5 5 , 当前有 249 249 249 5 5 5 ;


    分解出的 2 2 2 的个数 i i i 肯定是大于 500 500 500 的数 ;

    分解出的 5 5 5 的个数 j j j 值为 249 249 249 个 ;

    因此 1000 ! 1000! 1000! 末尾 0 0 0 的个数 是 249 249 249 个 ;

    更多相关内容
  • 本书系统地介绍了组合原理中最主要的基础知识,包括鸽笼原理、容斥原理、母函数、递归关系等必须掌握的基本内容。全书共七章,其内容详尽,既有基本内容,又有提高内容,较为全面地介绍了组合原理中的一些基本概念、...
  • 学习组合导航的大神著作,附有matlab代码与例子,帮助你更好的理解组合导航。
  • 一、鸽巢原理简单形式 、 二、鸽巢原理简单形式示例 2 、 三、鸽巢原理简单形式示例 3 、 四、鸽巢原理简单形式示例 4 、





    一、鸽巢原理简单形式



    鸽巢原理 :

    n + 1 n + 1 n+1 个物体 放到 n n n 个盒子 中 , 则

    一定存在一个盒子至少 含有 2 2 2 个 或 2 2 2 个以上的物体 ;


    鸽巢原理 实际上是 多对少的配置 ; 至少存在一个多对一的情况 ;





    二、鸽巢原理简单形式示例 1



    证明 : 在边长为 2 2 2 的正三角形中 , 有 5 5 5 个点 , 一定存在两个点的距离小于 1 1 1 ;


    将变成为 2 2 2 的正三角形 , 分为 4 4 4 个小的正三角形 , 每个边长为 1 1 1 ; 如下图 :

    在这里插入图片描述

    4 4 4 个小正方形中 , 绘制 5 5 5 个点 ;

    根据鸽巢原理 , 上述问题可以转为 5 5 5 个物体放入 4 4 4 个盒子中 , 至少有一个盒子中有 2 2 2 个 或 2 2 2 个以上的物体 ;

    在一个正三角形格子中 , 如果绘制了两个点 , 其距离肯定小于 1 1 1 ;





    三、鸽巢原理简单形式示例 2



    证明 : 9 × 3 9\times3 9×3 的方格 , 使用黑色 , 白色 两种颜色进行涂色 , 必定存在两列相同的涂色方案 ;


    先将可能的涂色方案枚举出来 : 一共只可能存在 2 3 = 8 2^3 = 8 23=8 种可能的涂色方案 ;

    在这里插入图片描述

    9 9 9 列方格中 , 使用 8 8 8 种模式进行涂色 ;

    可以等价理解为鸽巢原理的 : 9 9 9 个物体放到 8 8 8 个盒子中 , 则 至少有一个盒子中有 2 2 2 个 或 2 2 2 个以上的物体 ;

    因此至少有 2 2 2 列或 2 2 2 列以上的格子会被涂成一种颜色 ;





    四、鸽巢原理简单形式示例 3



    证明 : 空间中有 9 9 9 个格点 , 所有的两点连线的中点 , 有一个格点 ;


    格点指的是整数点 ;


    连线中点是格点的要求 : 空间坐标 ( x , y , z ) (x,y,z) (x,y,z) ( x ′ , y ′ , z ′ ) (x' , y' , z') (x,y,z) 有相同的奇偶性 , 即

    • x , x ′ x , x' x,x 同为奇数或偶数 ,
    • y , y ′ y , y' y,y 同为奇数或偶数 ,
    • z , z ′ z , z' z,z 同为奇数或偶数 ,

    此时这两个空间坐标的连线中点就是 格点 , 即整数点 ;


    下面分析三个坐标分别奇偶性相同时 , 中点是格点的原因 :

    连线中点坐标公式为 : ( x + x ′ 2 , y + y ′ 2 , z + z ′ 2 ) ( \dfrac{x + x'}{2} , \dfrac{y + y'}{2} , \dfrac{z + z'}{2} ) (2x+x,2y+y,2z+z)

    当奇偶性相同的时候 , 连线中点的空间坐标的三个数都是整数 ;


    空间坐标 ( x , y , z ) (x,y,z) (x,y,z) ( x ′ , y ′ , z ′ ) (x' , y' , z') (x,y,z) 的奇偶模式有 2 3 = 8 2^3 = 8 23=8 ; 分别是

    • 1 1 1 个坐标 x , x ′ x , x' x,x 奇偶相同 / 不同 , 两种情况 ;
    • 2 2 2 个坐标 y , y ′ y , y' y,y 奇偶相同 / 不同 , 两种情况 ;
    • 3 3 3 个坐标 z , z ′ z , z' z,z 奇偶相同 / 不同 , 两种情况 ;

    上述每个坐标有两种情况 , 三个坐标下来就是 2 × 2 × 2 = 8 2 \times 2 \times 2 = 8 2×2×2=8 种情况 , 这是乘法原则 ;


    空间中 9 9 9 个格点 , 每个格点的奇偶模式有 8 8 8 种 ;

    可以等价理解为鸽巢原理的 : 9 9 9 个物体放到 8 8 8 个盒子中 , 则 至少有一个盒子中有 2 2 2 个 或 2 2 2 个以上的物体 ;

    因此至少有 2 2 2 个或 2 2 2 个以上的格点的奇偶模式是相同的 ;

    因此 : 2 2 2 个奇偶模式相同的格点连接的中点 , 肯定是格点 ;

    展开全文
  • 组合模式 基本介绍 组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的层次关系。 组合模式依据树形结构来组合对象,用来表示部分以及整体...

    组合模式

    基本介绍

    1. 组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的层次关系。
    2. 组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
    3. 这种类型的设计模式属于结构型模式。
    4. 组合模式使得用户对单个对象和组合对象的访问具有一致性,即:组合能让客
      户以一致的方式处理个别对象以及组合对象

    解决的问题

    1. 组合模式解决这样的问题,当我们的要处理的对象可以生成一颗树形结构,而我们要对树上的节点和叶子进行操作时,它能够提供一致的方式,而不用考虑它是节点还是叶子
    2. 对应的示意图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DZ9Bm81V-1643880828541)(F:\StudyNotepad\img\image-20211122183230228.png)]

    实例演示

    现代计算机一般分为具有以下部件:键盘、显示器、机箱、鼠标。而机箱内部包括了主板、硬盘、电源等。主板是主机的心脏,其上面一般又插入了CPU,内存,显卡等设备,请用组合模式描述一台计算机,并尝试根据自己的对游戏的知识,实现一台电脑,能进行“绝地求生”游戏。

    分析

    我们应该先找到哪些是叶子结点,哪些是根节点。含有其他组件的是根节点(也就是能包含其他组件),最小的节点就是叶子结点,那么它只有最基本的功能。

    1)UML类图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hA6k3IPk-1643880828544)(F:\StudyNotepad\img\image-20211122183510729.png)]

    2)创建父类

    不管它是叶子结点还是根节点它本身都是一个组件,只是能够使用的功能不同

    /*
    * 定义一个基本的组件,不管它其中还包含了什么首先它都是电脑的组件
    * */
    public abstract class OriginalComponent {
        private String name;
        private String brand;
    
        public OriginalComponent(String name, String brand) {
            this.name = name;
            this.brand = brand;
        }
    
        /*
         * 我们先以最小组件的角度来看,它可以有哪些方法,其他如CPU这些
         * 也是一个类,但是当它们继承的这个父类的时候,这些方法的使用具体
         * 还要看它们的重写。在父类中默认我们的实现是抛出异常,也就是说
         * 如果继承的类不重写这个方法,那么就是没有使用这个方法的权限。
         * */
        protected void add(OriginalComponent originalComponent){
            throw new UnsupportedOperationException();
        }
    
        protected void remove(OriginalComponent originalComponent){
            throw new UnsupportedOperationException();
        }
    
        /*
        * 输出组件的信息是基本的功能,应该是每一个组件都有的,那么我们就将这个
        * 方法定义为抽象的,每一个继承父类的子类都要实现这个方法。
        * */
        protected  abstract void print();
    }
    

    3)根节点

    就如同前面所说,根节点和叶子结点的区别在于继承父类以后所能用的功能。

    这里就以机箱为例。

    /*
    * 机箱内部也含有其他组件
    * */
    public class ComputerCase extends OriginalComponent{
        List<OriginalComponent> componentList = new ArrayList<>();
    
        public ComputerCase(String name, String brand) {
            super(name, brand);
        }
    
        @Override
        protected void add(OriginalComponent originalComponent) {
            componentList.add(originalComponent);
        }
    
        @Override
        protected void remove(OriginalComponent originalComponent) {
            componentList.remove(originalComponent);
        }
    
        @Override
        protected void print() {
            for (OriginalComponent originalComponent : componentList) {
                System.out.println("---机箱---");
                originalComponent.print();
            }
        }
    }
    

    4)叶子结点

    叶子结点只有最基本的功能,那就是输出信息。

    以其中的一个叶子结点CPU为例

    public class CPU extends OriginalComponent{
    
        public CPU(String name, String brand) {
            super(name, brand);
        }
    
        @Override
        protected void print() {
            System.out.println("部件名称:"+this.getName()+"\t 部件品牌"+getBrand());
        }
    }
    

    5)组合

    将每一个部件包含到管理它的类中。

    public class Client {
        public static void main(String[] args) {
            Computer computer = new Computer("电脑", "pox");
            ComputerCase computerCase = new ComputerCase("机箱", "pox");
            ComputerMotherboard computerMotherboard = new ComputerMotherboard("主板", "pox");
            ComputerKeyboard computerKeyboard = new ComputerKeyboard("键盘", "pox");
            Memory memory = new Memory("内存条", "pox");
    
            Application application = new Application("应用", "pox");
            Game game = new Game("绝地求生", "蓝洞");
    
            computer.add(computerCase);
            computer.add(computerKeyboard);
            computerCase.add(computerMotherboard);
            computerMotherboard.add(memory);
            computer.add(application);
            application.add(game);
    
            computer.print();
        }
    }
    

    6)测试

    最后一个问题,实现游戏。我们换一个想法,游戏首先是一个应用,其次它是应用中的一个组件。然而应用也是电脑的组成部分,直接将它游戏添加到组件中即可。

    public class Game extends OriginalComponent{
    
        public Game(String name, String brand) {
            super(name, brand);
        }
    
        @Override
        protected void print() {
            System.out.println("游戏名称:"+this.getName()+"\t 游戏公司: "+getBrand());
            System.out.println("安装完毕~~");
            System.out.println("启动游戏....进入战场");
        }
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sz2S1lB8-1643880828546)(F:\StudyNotepad\img\image-20211122184432580.png)]

    小结

    不管它包含多少组件,首先它都是这个整体的组成部分。对于包含有其他组件的组件,那么就可以实现更多的方法来包含其他组件(也就是根节点)。对于不含有其他组件的组件就是最基本的组件,那么它只需要实现最基本的功能即可。

    补充

    关于HashMap,源码也是一种组合模式。

    首先是有一个最基本的接口Map(源码中它将我们的例子中的OriginalComponent的一些方法抽取出来创建了一个更加高的接口),在Map中就已经定义了一些如put、putAll等的方法。HashMap并不是直接实现了Map的接口,而是通过继承一个抽象类AbstractMap(就是类似我们这个例子中的OriginalComponent最原生的组件定义),在AbstractMap中实现了一些基本的方法,还有一些如put等的方法,也是默认抛出异常,如果后续继承的类要使用这些方法,那必定只有重写这些方法才能使用。

    对于这个组件树中的叶子结点,在HashMap中通过内部类 - Node来实现叶子组件,当进行调用put等方法时,先会将数据包装到这个Node中然后在存放到HashMap中,实现了对组件的管理。

    get()方法也是通过查找Node方式来查找。

    =====HashMap部分源码,关于put======
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    
    =====调用putVal方法存放=====
    // 部分源码
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        // 存放到Node中
        Node<K,V>[] tab; Node<K,V> p; int n, i;
    }
    

    代理模式

    基本介绍

    1. 代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
    2. 被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象
    3. 代理模式有不同的形式, 主要有三种 静态代理、动态代理 (JDK代理、接口代理)和 Cglib代理 (可以在内存动态的创建对象,而不需要实现接口, 他是属于动态代理的范畴) 。

    静态代理

    静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类 。

    实例演示

    请使用代理模式实现一个功能:假设要实现一个去哪儿网站,其可以代理航空公司卖机票,也可以代理火车站卖火车票,还可以代理汽车站卖汽车票,分别收取票价的5%,3%, 1%作为代理费。

    1)UML类图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4eiRKke1-1643880921389)(F:\StudyNotepad\img\image-20211122213327890.png)]

    2)创建公共接口

    代理的方法,需要相同,那么代理的对象和被代理的对象都要实现相同的接口,这里先定义接口

    public interface SellTickets {
        void sell();
        // 这里getname是为了后续分辨票的类型
        String getName();
    }
    
    3)创建实现类

    定义具体的票的名字和实现买票细节

    public class AirTickets implements SellTickets{
        private String name = "Air";
    
        @Override
        public void sell() {
            System.out.println("售卖飞机票~~");
        }
    
        @Override
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    4)编写动态代理类

    同理代理的也是同样的功能。因此也需要实现父类接口

    public class GoWhereProxy implements SellTickets{
        SellTickets sellTickets;
        private String name;
    
        public GoWhereProxy(SellTickets sellTickets) {
            name = "去哪儿";
            this.sellTickets = sellTickets;
        }
    
        /*
        * 这里可以根据传入的票的类型,做出相应的功能
        * */
        @Override
        public void sell() {
            if (sellTickets.getName().equals("Air")){
                System.out.println("飞机票收取5%手续费");
                sellTickets.sell();
                System.out.println("出票~~");
            } else if (sellTickets.getName().equals("Bus")){
                System.out.println("汽车票收取1%手续费");
                sellTickets.sell();
                System.out.println("出票~~");
            } else if (sellTickets.getName().equals("Train")){
                System.out.println("火车票收取3%手续费");
                sellTickets.sell();
                System.out.println("出票~~");
            }
        }
    
        @Override
        public String getName() {
            return name;
        }
    }
    
    5)测试

    静态代理为了实现售卖多种票的类型,则需要在公共接口中添加一个额外的属性,getName(但对于代理对象来说他实际在这个例子中是不需要这个方法的)。可不可以在不添加额外的方法的情况下实现不同票的代理售卖呢?

    动态代理

    public class Client {
        public static void main(String[] args) {
            AirTickets airTickets = new AirTickets();
            BusTicket busTicket = new BusTicket();
            TrainTicket trainTicket = new TrainTicket();
    
            /*
            * 开设三个窗口,每个窗口售卖指定类型的票
            * 分别代理飞机、汽车、火车
            * */
            GoWhereProxy goWhereProxy1 = new GoWhereProxy(airTickets);
            goWhereProxy1.sell();
    
            GoWhereProxy goWhereProxy = new GoWhereProxy(busTicket);
            goWhereProxy.sell();
    
            GoWhereProxy goWhereProxy2 = new GoWhereProxy(trainTicket);
            goWhereProxy2.sell();
        }
    }
    
    6)结果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yw6F3uCS-1643880921391)(F:\StudyNotepad\img\image-20211122214044057.png)]

    小结

    优点:在不修改目标对象的功能前提下, 能通过代理对象对目标功能扩展

    缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类

    一旦接口增加方法,目标对象与代理对象都要维护

    动态代理

    基本介绍

    1. 代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理
    2. 代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象
    3. 动态代理也叫做:JDK代理、接口代理

    需要实现Java底层的代理类来实现,根据接收类型来实现不同的代理。

    实例测试

    1)UML类图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dVgLAiQh-1643880921392)(F:\StudyNotepad\img\image-20211122215351375.png)]

    2)创建公共接口

    和上面的一样也需要定义一个基本接口,所有的售票类型都是售票的一种,将最基本的售票行为抽取出来为一个公共接口。

    public interface SellTickets {
        void sell();
    }
    
    3)实现公共接口

    这里以BusTicket为例

    public class AirTicket implements SellTickets{
        @Override
        public void sell() {
            System.out.println("售卖飞机票~~");
        }
    }
    
    4)编写动态代理

    底层是通过Java的代理类包来实现,具体的实现方式是通过类的反射来获取类的类型、类中的接口名、类继承的接口等一系列信息。通过获取的信息,来实现不同的传入类型,进行不同的代理。

    public class DynamicProxy {
        private Object target;
    
        public DynamicProxy(Object target) {
            this.target = target;
        }
    
        /*
        * 这里是在获取动态代理类,这个动态代理类会根据,传入的类的类型来进行代理
        * 就可以通过这里将票的类型不同而不同代理方式
        * 这里的判断条件就是通过类的反射来获取到类的名称。通过类的名字不同,就可以判断
        * 是不同的票的类型。
        * */
        public Object getProxyInstance(){
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("代理模式开始~~");
                            
                            /*
                            * target.getClass().getName().equals("dynamicproxy.AirTicket")就可以进行判断来做出不同的代理
                            * 为什么是:dynamicproxy.AirTicket,这个其实可以通过在控制台来打印获取到名称,这里我就是通过
                            * System.out.println(target.getClass().getName());来在控制台输出获取到类的名称的
                            * */
                            /*
                            * 11.30改进
                            * - 将获取类的信息改为instance判断
                            * */
                            if (target instanceof AirTicket){
                                System.out.println("收取5%的手续费");
                            } else if (target instanceof TrainTicket){
                                System.out.println("收取3%手续费");
                            } else if (target instanceof BusTicket){
                                System.out.println("收取1%手续费");
                            } else {
                                System.out.println();
                            }
    
                            Object invoke = method.invoke(target, args);
                            System.out.println("出票~~");
                            return invoke;
                        }
                    });
        }
    }
    

    小结

    就是通过反射来获取不同的代理类型,最后达到不同的代理方式。代理模式在多出源码都有使用,通过代理模式可以实现对方法的增加、扩展等,通常和反射一起使用。

    展开全文
  • vc++编写的bmp位图组合成avi动画源代码例子 vc++书籍上的经典例子保证可以使用
  • 容斥原理 就是人们为了不重复计算重叠部分,想出的一种不重复计算的方法。 先来认识一下这两个符号:与(如图) 蓝色的圈就是c1c2,红色的圈围起来的就是c1c2 二.例题:组合数学 1.题目 1.1.题目描述 八是...

    一.容斥原理

    就是人们为了不重复计算重叠部分,想出的一种不重复计算的方法。

    先来认识一下这两个符号:\bigcap\bigcup(如图)

    蓝色的圈就是c1\bigcapc2,红色的圈围起来的就是c1\bigcupc2

    二.例题:组合数学

    1.题目

    1.1.题目描述

    八是个很有趣的数字啊。八=发,八八=爸爸,88=拜拜。当然最有趣的还是8用二进制表示是1000。怎么样,有趣吧。当然题目和这些都没有关系。 某个人很无聊,他想找出[a,b]中能被8整除却不能被其他一些数整除的数。

    1.2.输入

    第一行一个数n,代表不能被整除的数的个数。 第二行n个数,中间用空格隔开。 第三行两个数a,b,中间一个空格。 a < =b < =1000000000

    1.3.输出

    一个整数,为[a,b]间能被8整除却不能被那n个数整除的数的个数。

    1.4.样例输入

    3

    7764 6082 462

    2166 53442

    1.5.样例输出

    6378

    1.6.提示

    对于30%的数据, 1 ≤n ≤5,1 ≤a ≤ b ≤ 100000。
    对于100%的数据,1 ≤ n ≤15,1 ≤ a ≤ b ≤ 10^9,N个数全都小于等于10000大于等于1。

     2.思路

    这道题一看就是用容斥原理做吧,如果我们用ans表示答案,用B表示a到b的范围内可以被8整除的所有数,用E表示a到b范围内的所有数,Ai表示那n个要求不能整除的数,可以想到公式:

    ans=B\bigcap (E-A_{1}\bigcup A_{2}\bigcup A_{3}\bigcup......\bigcup A_{n} )

    它的意义就是:所有范围内的数减去所有能被那n个数整除的数与所有范围内能被8整除的数的并集

    好,那么我们现在的问题就是如何求这些并集。(注意求两个数的并集就是求两个数的最小公倍数)

    先举一个例子:假如有两个要求不被整除的数(如图,那两个数分别为1号圈和2号圈):

    那么,ans=8-8\bigcap 1+8\bigcap 1\bigcap 2-8\bigcap 2也就是:ans=8-①-②+②-②-③ 

    再来一个稍复杂的:

    继续像例子1这样推:

    ans=8-8\bigcap 6082+ 8\bigcap 6082\bigcap 462-8\bigcap 6082\bigcap 462\bigcap 7764+8\bigcap 6082\bigcap 7764-8\bigcap 462+8\bigcap 462\bigcap 7764-8\bigcap 7764

    说人话,就是:ans=8-(①+⑤+④+②)+(②+④)-(④)+(④+⑤) -(③+②+④)+(④) -(④+⑤+⑥) 

    可化简为:ans=8-①-②-④-③-⑤-⑥,就是我们想要求的答案了。大家可以发现,我打了下划线的部分是各个完整的部分,分别是8与其他数分别第一次并集

    然后8与这个数并集之后,又依次与其他的数继续并集,并且不重不漏,还有,在一个完整的部分里第奇数次并集相减,第偶数次相加,如:ans=8-(①+⑤+④+②)+(②+④)-(④)+(④+⑤) -(③+②+④)+(④) -(④+⑤+⑥) 

    从8的集合开始,第0次加上8的集合内的所有数,到8\bigcap 6082开始第1次-(①+⑤+④+②)相减,第2次(②+④)相加,然后发现不能再并下去了,又回到8\bigcap 6082,开始新的第1次-(),第2次(④+⑤),发现也不能再走下去了,就到了8\bigcap 462,继续走下去就走完了。所以,这就是一个递归进行的过程,一个深搜就完事了。

    void dfs (int k, int Index, LL v){//k代表第几次并集,Index代表到了第几个集合,v代表这个集合,如v=8,就代表8的倍数这个集合
        if (v > b)//超出范围就没有意义
            return ;
        if (k % 2 == 0)//第偶数次加,第基数次减
            ans += b / v - a / v;
        else
            ans -= b / v - a / v;
        for (int i = Index + 1; i <= n; i ++){
            LL t = lcm (v, m[i]);//求着两个集合的并集
            dfs (k + 1, i, t);//递归求解
        }
    }

    3.代码

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    #define LL long long
    int n, m[130], a, b;
    LL ans;
    LL gcd (LL a, LL b){//最大公因数
        if (! b)
            return a;
        return gcd (b, a % b);
    }
    LL lcm (LL a, LL b){//最小公倍数
        return a * b / gcd (a, b);
    }
    void dfs (int k, int Index, LL v){//k代表第几次并集,Index代表到了第几个集合,v代表这个集合,如v=8,就代表8的倍数这个集合
        if (v > b)//超出范围就没有意义
            return ;
        if (k % 2 == 0)//第偶数次加,第基数次减
            ans += b / v - a / v;
        else
            ans -= b / v - a / v;
        for (int i = Index + 1; i <= n; i ++){
            LL t = lcm (v, m[i]);//求着两个集合的并集
            dfs (k + 1, i, t);//递归求解
        }
    }
    int main (){
        scanf ("%d", &n);
        for (int i = 1; i <= n; i ++)
            scanf ("%d", &m[i]);
        scanf ("%d %d", &a, &b);
        dfs (0, 0, 8);//从第0次开始
        printf ("%lld\n", ans);
        return 0;
    }
    

    4.感想

    这道题的深搜是最考验人的,有时候只要带一些例子进去算一下就豁然开朗了。

    展开全文
  • 组合数学之二 —— 容斥原理及应用

    千次阅读 2017-12-20 15:48:15
    内容主要来自《组合数学》+博主的思考容斥原理之前在“组合数学一”中提到过容斥原理 我们在这里直接给出推论: 设Ai表示在集合S中拥有特征Pi的元素子集,则集合S中至少具有性质P1,P2,P3,…,Pm之一的对象个数由下...
  • TRIZ系列-创新原理-5-合并原理

    千次阅读 2014-10-11 13:18:42
    组合原理表述如下:1)在空间上,将相同的物体或者相关的操作加以组合;2)在时间上,将相同或相关的操作进行合并。在空间上进行组合其实是一种组件集成或者功能集成,可以提高系统的性能:整体性和便利性。提高系统...
  • Matlab主成分分析(根据例子原理)

    千次阅读 2020-09-14 20:50:28
    主成分分析就是设法将原来众多具有一定相关性的指标,重新组合成几个新的相互无关的综合指标,并且尽可能多地反映原来指标的信息。它是数学上的一种降维方法。 其中 X1表示人均食品消费; X2表示人均衣着消费; X3...
  • 组合关系和聚合关系.

    千次阅读 2020-12-19 12:16:30
    1组合关系和聚合关系浙江广播电视大学章一鸣(2004年10月14日)一、组合关系和和聚合关系的提出组合关系和聚合关系是现代语言学中的一个基本原理。《语言学纲要》上说:“符号和符号组合起来的关系称为符号的组合关系...
  • 鸽巢原理 天上有十个鸽子,这十个鸽子要飞到九个鸽巢里,无论怎样飞,我们会发现至少会有一 个鸽巢里面放两个鸽子,这一现象就是我们所说的“鸽巢原理”。鸽巢定理由狄里克利于1834 年提出,当时命名为 ...
  • 容斥原理详解

    千次阅读 2020-04-13 19:29:56
    容斥原理是一种重要的组合数学方法,可以让你求解任意大小的集合,或者计算复合事件的概率。 描述 容斥原理可以描述如下: 要计算几个集合并集的大小,我们要先将所有单个集合的大小计算出来,然后减去所有两个...
  • Java线程池原理讲解

    千次阅读 2022-01-21 15:03:18
    Java线程池核心原理讲解
  • 认识CPU的工作原理

    万次阅读 多人点赞 2018-08-01 11:40:18
    学习CPU的工作原理 ...因此从这个意义上来说,CPU正是由晶体管组合而成的。 简单而言,晶体管就是微型的电子开关。它们是构建CPU的基石,你可以把一个晶体管当做一个点灯开关,它们有个操作位,分...
  • CRP原理的简单例子

    千次阅读 2018-06-23 11:36:12
    CRP:英文全名Composite Reuse Principle,译为复合的复用原则。可以解释为类应该通过复合的使用(包含实现所需功能的其他类的实例)实现多态行为和代码重用,而不是从基或父类继承。代码示例:class Employee { ...
  • 《自动控制原理》个人笔记(来自ppt课件)

    万次阅读 多人点赞 2018-12-28 21:43:09
    找出所有可能组合的2个,3个,……找出所有可能组合的2个,3个,…… 互不接触(无公共节点)回路,并写出 回路增益 ; 写出 信号流图特征式 ; 观察并写出所有从输入节点到输出节点的 前向通道的增益 : ...
  • 在前一片文章(SkLearn 对上证50成分股聚类 )中简单介绍了投资组合优化理论,在此进一步介绍下该理论,以及如何进行Portfolio Optimization。1. Markowitz投资组合理论Markowitz投资组合理论是投资组合优化的理论基础...
  • 抽屉原理解释及简单举例

    千次阅读 2018-12-12 23:13:51
    解释    桌上有十个苹果,要把这十个苹果放到九个抽屉里,无论怎样放,我们会发现至少会有一个抽屉里面至少放两个苹果。这一现象就是我们所说的“抽屉原理”。...它是组合数学中一个重要的原理。   ...
  • Systrace的工作原理例子解读

    千次阅读 2017-07-05 10:38:31
    Systrace的工作原理例子解读译文地址:https://source.android.com/devices/tech/debug/systrace如果图片显示有问题,请访问简书,地址http://www.jianshu.com/p/6f528e862d31systrace是一个分析android性能问题的...
  • Socket原理讲解

    万次阅读 多人点赞 2019-07-18 15:50:36
    6、一个例子 1、网络中进程之间如何通信? 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道、FIFO、消息队列) 同步(互斥量、条件变量、读写锁、文件和写记录...
  • 传感器可以看成是一个数据采集终端,其自身也是一个...本文就是探讨这些传感器自身的工作原理,以及它们是如何传递信息的 。 至于有大量的单体传感器构建的构建的微型通信系统,即传感网,就在单独的文章中探讨。...
  • 深度学习初步,全连接神经网络,MLP从原理到实现(二)原理部分,过拟合,激活函数,batchsize和epochs,训练DL模型的建议 深度学习初步,全连接神经网络,MLP从原理到实现(三)实现部分,用java实现MLP 下面的...
  • 计算机网络—网络原理之TCP/IP协议(一)

    万次阅读 多人点赞 2022-04-16 00:00:55
    一文深度图文解析网络原理之TCP/UDP协议,及其机制,以及常考面试问题,TCP/IP协议有这个一篇就够了
  • 为什么编译原理被称为龙书?

    千次阅读 多人点赞 2020-07-17 08:32:21
    什么是编译原理 计算机是只认识二进制的,但是我们平常开发中根本不会使用二进制进行开发,我们使用的都是 Java、C 这类的高级语言,每种语言都会经过一系列的转换才能被计算机识别,那么到底是谁做的这项工作呢?...
  • Spring MVC : 注解@ControllerAdvice的工作原理

    千次阅读 多人点赞 2019-08-23 16:21:14
    Spring MVC中,通过组合使用注解@ControllerAdvice和其他一些注解,我们可以为开发人员实现的控制器类做一些全局性的定制,具体来讲,其效果如下 : 结合@ExceptionHandler使用 ==> 添加统一的异常处理控制器方法...
  • 三,例子分析 假设现在在一个CDMA系统中有很多站在相互通信,每一个站所发送的是数据比特和本站的码片序列的乘积,因而是本站的码片序列(相当于发送1和该码片序列的二进制反码(相当于发送比特 0)的组合序列,或...
  • Spring Cloud Hystrix原理简析

    千次阅读 2019-05-20 08:12:45
    现实生活中,可能大家都有注意到家庭电路中通常会安装一个保险盒,当负载过载时,保险盒中的保险丝会自动熔断,以保护电路及家里的各种电器,这就是熔断器的一个常见例子。Hystrix中的熔断器(Circuit Breaker)也是起...
  • 计算机组成原理 — ARM 体系结构

    万次阅读 2020-05-05 13:30:58
    一旦用扩展名 *.s 编写程序就需要把它与其进行组合并与 ld 链接起来: 我们从最底层来看下,在最底层,电路上有电信号,信号是将电压切换为两个电平来形成的,例如 0 伏(关)或 5 伏(开)。 因为只是我们不能轻易...
  • 【MySQL笔记】正确的理解MySQL的MVCC及实现原理

    万次阅读 多人点赞 2019-07-05 15:43:06
    MVCC实现原理 MVCC相关问题 前提概要 什么是MVCC? MVCC MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 165,438
精华内容 66,175
关键字:

关于组合原理的例子