zoukankan      html  css  js  c++  java
  • uva 571 Jugs

    数论题

    题意:

    有无限的水供应,另外有AB两个杯子,他们有容量,分别为ca和cb,满足0<ca<=cb,并且ca和cb互质
    一开始两个杯子都没有水。一种操作是,你能往一个杯子加水,但必须把这个杯子加满,一种操作是倒水,但一定要把水倒空,一种操作是把一个杯子的水倒给另一个杯子,但要求是至少使一个杯子为空或者另一个杯子。现在给你一个数字n,n<=cb,现在的任务是使B杯的水量为n,至于A杯的水量是多少都行,问你要怎么做。

    这题对于一个case其实有多种答案,不过题目对于输出并没有要求并没有需要优化,任意一组可行解即可

    这题一开始没有头绪,从推理的角度来看这题,但是一直找不到出路。题目归类在数学类,条件中ca与cb互质,这个东西肯定有用,但是想不出来。后来看了一下题解,明白了,所以自己写一下证明

    先来看一个特列: 由于 0<ca<=cb  ,  N<=cb 且题目保证一定有解,所以当ca=cb时,不难推理出必然有N=ca=cb,这样的话,只要一步操作就是往B中加满水。

    当 ca<cb ,  N=cb,  同样是一步操作往B中加满水。  所以特殊情况就是N=cb,直接往B中加水

    下面讨论的是N<cb

    1.来看一个式子 x*A , B , 其中x的范围是[1,B-1],x*A无法被B整除,(因为A与B互质,A不能整除B(没有任何除了1以外的公因子),x也不可能整除B,因而x*A不可能整除B)

    2.那么x*A mod B=r ,且r!=0;下面证明一个最重要的结论,当 x1!=x2是,r1!=r2

    反证法:假设:x1!=x2,r1=r2

    我们先约定x1>x2,r1=r2=r

    x1*A =  m1*B+r;    

    x2*A =  m2*B+r;

    上面两式相减 (x1-x2)*A=(m1-m2)*B     ------>    (x1-x2)*A/B=m1-m2

    换句话说,(x1-x2)*A能被B整除,而1<=x1-x2<=B-1,这与第1条结论是矛盾的

    所以假设不成立,当x1!=x2时,r1!=r2

    3.基于1和2,可以得到最后的结论  x*A , x范围[1,B-1] , 而x不同时,r也不同,可知知道,当x从1到B-1枚举,r的取值也将在[1,B-1],只是顺序不一定
    换句话说,x枚举完,就能得到所有可能的r值,而N<cb,一定会得到一个N的值

    4.最后就是代码实现,只要理清一下逻辑关系即可

    #include <cstdio>
    #include <cstring>
    int ca,cb,n,a,b;
    
    
    int main()
    {
        while(scanf("%d%d%d",&ca,&cb,&n)!=EOF)
        {
            if(cb==n)
            {
                printf("fill B\n");
                printf("success\n");
                continue;
            }
            a=b=0;
            while(b!=n)
            {
                if(a==0)  //A瓶为空,加满
                {
                    printf("fill A\n");
                    a=ca;
                }
                if(b<cb)  //b瓶没没有满
                {
                    printf("pour A B\n");
                    if(b+ca>cb)  //B先满,A不为空
                    {
                        a=ca-(cb-b);
                        b=cb;
                    }
                    else      //A为空,B未满或者满都有可能
                    {
                        b=b+a;
                        a=0;
                    }
                }
                if(b==cb)
                {
                    printf("empty B\n");
                    b=0;
                    printf("pour A B\n");
                    b=a;
                    a=0;
                }
            }
            printf("success\n");
        }
        return 0;
    }
  • 相关阅读:
    想要学习设计模式,你得先会看类图,一张图读懂UML
    UML类图中箭头的含义
    DDD学习
    Customize your build
    WaitAll vs WhenAll
    When does a C# Task actually start?
    UE4中多种颜色轮廓线的后期处理
    [UE4]武器碰撞
    动态材质实例(Dynamic Material Instance)
    卷积运算
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2869587.html
Copyright © 2011-2022 走看看