NEFU 358 埃及分数(迭代加深,数学)

埃及分数

Problem:358
Time Limit:1000ms
Memory Limit:65536K

Description

	对于每一个非负有理数,我们知道它一定能划归成某些特殊真分数之和,特殊真分数要满足它们的分子为1,但是我们知道,对于无穷级数1/2+1/3+1/4…。虽然,它是发散的,但是改级数增长得极为缓慢,例如到了数百万之后,和也在18~19左右。
	若干年来,不断有人宣称发现了该级数的特殊性质,这些都对这个问题的研究起到了深远的影响。
	你的任务来了,要求给你个真分数,你需要将其化简为最少的若干特殊真分数之和,你要输出这个序列(序列按递增序)。
	如果有不同的方案,则分数个数相同的情况下使最大的分母最小。若还相同,则使次大的分母最大……以此类推。
	如: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 
最好的是最后一种,因为18 比180, 45, 30,都小。

Input

多组数据输入.
每组输入一行,a,b,(0<=a<b<=1000)表示要化简的数为a/b

Output

输出一个算式,格式见样例。每个+、=号两边都没空格。

Sample Input

3 7

Sample Output

3/7=1/4+1/7+1/28
题意:中文题不解释

思路:第一次做迭代加深...真难啊。

迭代加深去枚举拆出来几个子分数

当可以达到b%a==0的时候满足条件

题目似乎有点问题,我只判断了最大的最小就过了。

注意每一次枚举的下界是b/a,因为1/(b-a-1)大于a/b了

上界是(dep-k+1)*b/a,这里是假设后面的dep-k+1个数都跟这个数相等会等于这个,但是题目说了不能相等并且并且后面的分数分母比当前大,所以这是上界

还注意一点剪枝即可

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 10
int ans[N],d[N];
int dep,flag;
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
void dfs(int a,int b,int k)
{
    if(k>dep) return;
    if(b%a==0&&b/a>d[k-1])
    {
        d[k]=b/a;
        if(!flag||d[k]<ans[k])
            memcpy(ans,d,sizeof(d));
        flag=1;
        return;
    }
    int s=b/a;
    if(s<d[k-1]) s=d[k-1]+1;
    int t=(dep-k+1)*b/a;
    if(flag&&t>=ans[dep]) t=ans[dep]-1;
    for(int i=s;i<=t;i++)
    {
        d[k]=i;
        int m=gcd(a*i-b,b*i);
        dfs((a*i-b)/m,b*i/m,k+1);
    }
}
void solve(int a,int b)
{
    d[0]=1;
    flag=0;
    for(dep=1;dep<=N;dep++)
    {
        dfs(a,b,1);
        if(flag)
        {
            for(int i=1;i<dep;i++)
                printf("1/%d+",ans[i]);
            printf("1/%d\n",ans[dep]);
            break;
        }
    }
}
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        printf("%d/%d=",n,m);
        solve(n,m);
    }
    return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值