zoukankan      html  css  js  c++  java
  • 【Codevs1288】埃及分数

    Position:


    Description

      在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数。 如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。 对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越 好。 如: 19/45=1/3 + 1/12 + 1/180 19/45=1/3 + 1/15 + 1/45 19/45=1/3 + 1/18 + 1/30, 19/45=1/4 + 1/6 + 1/180 19/45=1/5 + 1/6 + 1/18. 最好的是最后一种,因为1/18比1/180,1/45,1/30,1/180都大。 给出a,b(0 < a < b < 1000),编程计算最好的表达方式。

    Input

    a b

    Output

    若干个数,自小到大排列,依次是单位分数的分母。

    Sample Input

    19 45

    Sample Output

    5 6 18

    Solution

    精简版本

    给定一个分数 A/B,要将其转换为单位分数之和。要求单位分数数量最少,且每个分数都不同。

    Source

    普通搜索枚举哪个数可以填显然会TLE,它会不断搜下去,爆LL,爆栈。
    那么怎么解决呢?采用迭代加深算法,限定分成的数目,如果当前可以,即为最小输出方案即可。
    剪枝(见check函数):当前可以搜的最大分数(由分数从大到小搜索)×剩余块数 < 还要搞的分数,就可以return了,因为之后不可能有解。

    Code

    // <math.cpp> - Wed Sep 28 08:14:53 2016
    // This file is made by YJinpeng,created by XuYike's black technology automatically.
    // Copyright (C) 2016 ChangJun High School, Inc.
    // I don't know what this program is.
    
    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #define IN inline
    #define RG register
    using namespace std;
    typedef long long LL;
    const int MAXN=100010;
    const int MAXM=100010;
    inline LL gi() {
    	register LL w=0,q=0;register char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')q=1,ch=getchar();
    	while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar();
    	return q?-w:w;
    }
    int n;LL as[MAXN];
    IN bool check(LL a,LL b,LL c,LL d){
        if(a*d>b*c)return 0;
        else return true;
    }
    IN void dfs(LL x,LL y,LL f,int d){
        if(x<0)return;
        if(d==1){
            if(x==1&&y>=f){
                printf("%d
    ",n);
                for(int i=n;i>=2;i--)
                    printf("%lld ",as[i]);
                printf("%lld",y);exit(0);
            }
            return;
        }
        for(RG LL i=f,g;check(x,y,d,i);i++){
            as[d]=i;g=__gcd(x*i-y,y*i);
            dfs((x*i-y)/g,y*i/g,i+1,d-1);
        }
    }
    int main()
    {
    	freopen("math.in","r",stdin);
    	freopen("math.out","w",stdout);
    	int x=gi(),y=gi();
        for(int i=1;;i++)n=i,dfs(x,y,1,i);
    	return 0;
    }
    

    Codevs这个

    注意这题和上面那道普通题不同:加数个数相同的,最小的分数越大越好。

    Source

    最后统计答案时,不直接exit(0);让它将这一层(迭代的深度)全搜完,统计最优答案。

    Code

    // <math.cpp> - Wed Sep 28 08:14:53 2016
    // This file is made by YJinpeng,created by XuYike's black technology automatically.
    // Copyright (C) 2016 ChangJun High School, Inc.
    // I don't know what this program is.
    
    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #define IN inline
    #define RG register
    using namespace std;
    typedef long long LL;
    const int MAXN=100010;
    const int MAXM=100010;
    inline LL gi() {
    	register LL w=0,q=0;register char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')q=1,ch=getchar();
    	while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar();
    	return q?-w:w;
    }
    int n;LL as[MAXN],sa[MAXN];bool flag;
    IN bool check(LL a,LL b,LL c,LL d){
        if(a*d>b*c)return 0;
        else return true;
    }
    IN void dfs(LL x,LL y,LL f,int d){
        if(x<0)return;
        if(d==1){
            if(x==1&&y>=f){
                if(y<sa[1]){
                    flag=true;sa[1]=y;
                    for(int i=n;i>=2;i--)sa[i]=as[i];
                }
            }
            return;
        }
        for(RG LL i=f,g;check(x,y,d,i);i++){
            as[d]=i;g=__gcd(x*i-y,y*i);
            dfs((x*i-y)/g,y*i/g,i+1,d-1);
        }
    }
    int main()
    {
    	freopen("math.in","r",stdin);
    	freopen("math.out","w",stdout);
    	int x=gi(),y=gi();flag=false;sa[1]=1e17;
        for(int i=1;;i++){
            n=i,dfs(x,y,1,i);
            if(flag){
                for(int i=n;i;i--)printf("%lld ",sa[i]);return 0;
            }
        }
    	return 0;
    }
    

    原型

    参考我的博客:SWUST626 分数分解

  • 相关阅读:
    SPOJ 1812 Longest Common Substring II(后缀自动机)(LCS2)
    HDU 4441 Queue Sequence(优先队列+Treap树)(2012 Asia Tianjin Regional Contest)
    HDU 4433 locker(DP)(2012 Asia Tianjin Regional Contest)
    HDU 4431 Mahjong(枚举+模拟)(2012 Asia Tianjin Regional Contest)
    NavigationBar的简单设置
    Android如何设置标题栏的高度
    android 在标题栏加上按钮
    MediaRecorder类介绍
    Android ADB server didn't ACK * failed to start daemon * 简单有效的解决方案
    2016/1/7 改 百文百鸡 水仙花数 百马百担
  • 原文地址:https://www.cnblogs.com/YJinpeng/p/5916528.html
Copyright © 2011-2022 走看看