18444 分数拆分

Description
输入正整数k(k<=1000),将1/k变为不少于2项,但不多于3项的1/(xi)之和,xi为正整数,且i表示序号

注:请使用long long

输入格式
多case,一行一个整数k

最后一行是0

输出格式
对每一个case,按等式最右边一项分母,由小到大排序输出满足条件的等式,最右边一项分母相同,则按最右边第二项,依次类推

每一个case完成后,输出一个空行(没有满足的等式时,也要输出该空行)

输入样例
2
3
4
0

输出样例
1/2=1/6+1/3
1/2=1/42+1/7+1/3
1/2=1/24+1/8+1/3
1/2=1/18+1/9+1/3
1/2=1/15+1/10+1/3
1/2=1/12+1/12+1/3
1/2=1/4+1/4
1/2=1/20+1/5+1/4
1/2=1/12+1/6+1/4
1/2=1/8+1/8+1/4
1/2=1/10+1/5+1/5
1/2=1/6+1/6+1/6

1/3=1/12+1/4
1/3=1/156+1/13+1/4
1/3=1/84+1/14+1/4
1/3=1/60+1/15+1/4
1/3=1/48+1/16+1/4
1/3=1/36+1/18+1/4
1/3=1/30+1/20+1/4
1/3=1/28+1/21+1/4
1/3=1/24+1/24+1/4
1/3=1/120+1/8+1/5
1/3=1/45+1/9+1/5
1/3=1/30+1/10+1/5
1/3=1/20+1/12+1/5
1/3=1/15+1/15+1/5
1/3=1/6+1/6
1/3=1/42+1/7+1/6
1/3=1/24+1/8+1/6
1/3=1/18+1/9+1/6
1/3=1/15+1/10+1/6
1/3=1/12+1/12+1/6
1/3=1/21+1/7+1/7
1/3=1/12+1/8+1/8
1/3=1/9+1/9+1/9

1/4=1/20+1/5
1/4=1/420+1/21+1/5
1/4=1/220+1/22+1/5
1/4=1/120+1/24+1/5
1/4=1/100+1/25+1/5
1/4=1/70+1/28+1/5
1/4=1/60+1/30+1/5
1/4=1/45+1/36+1/5
1/4=1/40+1/40+1/5
1/4=1/12+1/6
1/4=1/156+1/13+1/6
1/4=1/84+1/14+1/6
1/4=1/60+1/15+1/6
1/4=1/48+1/16+1/6
1/4=1/36+1/18+1/6
1/4=1/30+1/20+1/6
1/4=1/28+1/21+1/6
1/4=1/24+1/24+1/6
1/4=1/140+1/10+1/7
1/4=1/42+1/12+1/7
1/4=1/28+1/14+1/7
1/4=1/8+1/8
1/4=1/72+1/9+1/8
1/4=1/40+1/10+1/8
1/4=1/24+1/12+1/8
1/4=1/16+1/16+1/8
1/4=1/36+1/9+1/9
1/4=1/18+1/12+1/9
1/4=1/20+1/10+1/10
1/4=1/15+1/12+1/10
1/4=1/12+1/12+1/12

思路:

①、了解式子的格式为:1/k = 1/x + 1/y + 1/z,并且x >= y >= z > k
②、求z范围:因为x>=y>=z>k   所以1/x<=1/y<=1/z    又因为1/k = 1/x + 1/y + 1/z <= 3/z  所以 1/k <= 3/z  则z<=3*k
③、先判断两项的输出,即1/k = 1/y + 1/z
④、已知k,z,若拆分成两项成立,则根据关系,所求y一定为整数,1/y=1/k-1/z, 即 y=k*z/(z-k)
⑤、判断y是否为整数并且式子符合大小关系,如果符合,则输出
⑥、判断三项是否成立,即1/k=1/x+1/y+1/z
⑦、此时固定z,已知1/x+1/y的和为1/k-1/z,思路跟上面类似,将1/k-1/z的结果作为一项进行拆分,注意这个结果可能无法划分为1/某数的形式
⑧、求此时的较小数y的范围,此时y的范围为:k*z/(z-k)+1  ~  2*(k*z/(z-k))+1
⑨、已知k、y、z,若式子成立,则所求x一定为整数,因为1/x=1/k-1/y-1/z 所以x=k*y*z/(y*z-k*z-k*y)
⑩、判断x是否为整数并且式子符合大小关系,如果符合,则输出

代码:

#include <cstdio>
#include<iostream>
using namespace std;

int main()
{
    long long x, y, z, k;
    while (cin>>k && k)
    {
        //式子的格式为1/k = 1/x + 1/y + 1/z
        /*
        因为x>=y>=z>k   所以1/x<=1/y<=1/z    又因为1/k = 1/x + 1/y + 1/z <= 3/z  所以 1/k <= 3/z  则z<=3*k
        */
        for (z = k+1; z <= 3*k; z++)
        {
            //先判断两项是否成立,即1/k==1/y+1/z
            //已知k,z,若成立,则所求中y一定为整数,1/y==1/k-1/z, 即 y=k*z/(z-k)
            y=k*z/(z-k);
            if((k*z)%(z-k) == 0 && y>=z)//随着z的递增,y有可能小于z,则判断如果y大于z,则输出式子1/k==1/y+1/z
                printf("1/%lld=1/%lld+1/%lld\n",k,y,z);

            //判断三项是否成立,即1/k=1/x+1/y+1/z
            //已知1/x+1/y的和为1/k-1/z,思路跟上面类似,将1/k-1/z作为一项进行拆分,这个结果可能无法划分为1/某数的形式
            int p = k*z/(z-k);
            for(y=p+1; y <= 2*p+1; y++)
            {
                //因为1/x=1/k-1/y-1/z 所以x=k*y*z/(y*z-k*z-k*y)
                //若式子成立,则x一定为整数
                x=k*y*z/(y*z-k*z-k*y);
                if ((k*y*z) % (y*z-k*z-k*y) == 0 && x>=y && y>=z)//如果x>=y>=z,则输出
                    printf("1/%lld=1/%lld+1/%lld+1/%lld\n",k,x,y,z);
            }
        }
        printf("\n");
    }

    return 0;
}
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值