zoukankan      html  css  js  c++  java
  • ZOJ 3407 Doraemon's Cake Machine [数学]

    题意:

    最多有2000组测试样例,每组样例代表n,m;

    n代表要把蛋糕平分的份数,m代表必须进行多少次操作。

    一共有三种操作

    1.竖切   经过蛋糕圆心,将蛋糕整个向下切。

    2.横切   平行于蛋糕平面进行平切。

    3.复制某块小蛋糕    这种操作只能在1和2所有操作都进行完才能进行。

    求:

    最少进行多少次复制操作可以将蛋糕分为一样的恰好n种。注意需要用恰好m次操作。

    如果没有可行解输出-1。

    思路:

    假设进行三种操作的数目分别是xyz。然后连立两个式子把z消掉,get

    2x(y+1)-(x+y)=n-m;

    因为x+y+z=m且z>=0所以有x+y<=m;

    所以有2x(y+1)<=n;

    进而xy<n;(x和y都是非负整数)

    所以得到结论在符合要求的等式中必定有x<=sqrt(n)||y<=sqrt(n);

    所以对两者枚举到sqrt(n)即可。

    坑:

    我们应该明白,每次进行操作至少会使得蛋糕的数量增加1.所以当m>=n的时候直接输出-1.

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    const int inf=0x3f3f3f3f;
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--){
            long long ans=inf,n,m;
            scanf("%lld%lld",&n,&m);
            if(n<=m){
                printf("-1
    ");
                continue;
            }
            for(int i=1;i<=sqrt(n)+1;i++){
                if((n-m-i)%(2*i-1)==0&&n-m-i>=0){
                    long long y=(n-m-i)/(2*i-1);
                    if(i+y<=m){
                        ans=min(ans,m-i-y);
                    }
                }
            }
            for(int i=0;i<=sqrt(n)+1;i++){
                if((n-m+i)%(2*i+1)==0&&n-m+i>=0){
                    long long x=(n-m+i)/(2*i+1);
                    if(i+x<=m){
                        ans=min(ans,m-i-x);
                    }
                }
            }
            if(m+1==n)ans=0;
            if(ans==inf)ans=-1;
            printf("%lld
    ",ans);
        }
    }
  • 相关阅读:
    序列点,相关知识
    6.13 关键概念
    6.9 如何选择循环
    6.8 出口条件循环:do while
    6.7 逗号运算符
    6.6 其他赋值运算符:+=、-=、*=、/=、%=
    6.3.4 新的_Bool类型
    Oracle的表导入到PowerDesigner
    PowerDesigner连接Oracle数据库
    加了日期条件后查询结果慢了100倍
  • 原文地址:https://www.cnblogs.com/tun117/p/5412065.html
Copyright © 2011-2022 走看看