[51nod 1139]奇妙等式的解

题目描述

五个不同自然数a < b < c < d < e 满足a^2 + b^2 + c^2 + d^2 + e^2 = abcde。给出1个数N,求e <= N的全部的解。

构造

考虑构造算法。
假如a,b,c,d,e是合法解。
bcde-a,b,c,d,e也是合法解
同理有a,acde-b,c,d,e也是……
注意这里的合法解不考虑 a<b<c<d<e
可以证明所有解是联通的。

#include<cstdio>
#include<algorithm>
#include<map>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<ll,ll> pi;
typedef pair<pi,pi> pii;
typedef pair<pii,ll> piii;
const ll lim=2e18;
const int maxt=700000,maxx=40000;
map<piii,bool> ha;
piii zlt;
struct dong{
    ll a,b,c,d,e;
} ans[2500];
ll dl[maxt+1000][5],a[5],b[5];
int i,j,k,l,m,head,tail,top;
ll n,t;
bool czy;
bool cmp(dong a,dong b){
    if (a.a<b.a||a.a==b.a&&a.b<b.b) return 1;
    if (a.a==b.a&&a.b==b.b&&a.c<b.c||a.a==b.a&&a.b==b.b&&a.c==b.c&&a.d<b.d) return 1;
    if (a.a==b.a&&a.b==b.b&&a.c==b.c&&a.d==b.d&&a.e<b.e) return 1;
    return 0;
}
piii mk(ll a,ll b,ll c,ll d,ll e){
    pi l=make_pair(a,b),r=make_pair(c,d);
    pii m=make_pair(l,r);
    return make_pair(m,e);
}
int main(){
    //freopen("data.out","w",stdout);
    czy=1;
    /*fo(i,1,200)
        fo(j,i,200)
            fo(k,j,200)
                fo(l,k,200)
                    fo(t,l,200)
                        if (i*i+j*j+k*k+l*l+t*t==i*j*k*l*t){
                            printf("%d %d %d %d %d\n",i,j,k,l,t);
                        }*/
    head=0;tail=1;
    dl[1][0]=1;dl[1][1]=1;dl[1][2]=3;dl[1][3]=3;dl[1][4]=4;
    zlt=mk(1,1,3,3,4);
    ha[zlt]=1;
    /*dl[2][0]=1;dl[2][1]=3;dl[2][2]=5;dl[2][3]=12;dl[2][4]=179;
    zlt=mk(1,3,5,12,179);
    ha[zlt]=1;
    dl[3][0]=1;dl[3][1]=3;dl[3][2]=4;dl[3][3]=35;dl[3][4]=417;
    zlt=mk(1,3,4,35,417);
    ha[zlt]=1;
    dl[4][0]=1;dl[4][1]=3;dl[4][2]=5;dl[4][3]=44;dl[4][4]=657;
    zlt=mk(1,3,5,44,657);
    ha[zlt]=1;
    dl[5][0]=1;dl[5][1]=3;dl[5][2]=9;dl[5][3]=23;dl[5][4]=620;
    zlt=mk(1,3,9,23,620);
    ha[zlt]=1;
    dl[6][0]=1;dl[6][1]=3;dl[6][2]=12;dl[6][3]=31;dl[6][4]=1115;
    zlt=mk(1,3,12,31,1115);
    ha[zlt]=1;
    dl[7][0]=1;dl[7][1]=4;dl[7][2]=9;dl[7][3]=33;dl[7][4]=1187;
    zlt=mk(1,4,9,33,1187);
    ha[zlt]=1;*/
    while (head<tail){
        if (tail>=maxt){
            t=t;
            break;
        }
        if (head==1331){
            t=t;
        }
        ++head;
        fo(i,0,4) a[i]=dl[head][i];
        fo(i,0,4){
            fo(j,0,4) b[j]=a[j];
            t=1;
            czy=1;
            fo(j,0,4)
                if (j!=i){
                    if (t>lim/a[j]){
                        czy=0;
                        break;
                    }
                    t*=a[j];
                }
            if (!czy) continue;
            t-=a[i];
            b[i]=t;
            sort(b,b+5);
            if (b[0]<=0) continue;
            /*if (tail>=maxx) {
                czy=1;
                fo(j,1,4)
                    if (b[j]==b[j-1]){
                        czy=0;
                        break;
                    }
                if (!czy) continue; 
            }*/
            zlt=mk(b[0],b[1],b[2],b[3],b[4]);
            if (b[0]==9&b[1]==23&&b[2]==620&&b[3]==128337&&b[4]==1830085619){
                t=t;
            }
            if (!ha[zlt]){
                ha[zlt]=1;
                ++tail;
                fo(j,0,4) dl[tail][j]=b[j];
            }
        }
    }
    fo(i,1,tail)
        if (dl[i][0]==1&&dl[i][1]==3&&dl[i][2]==5&&dl[i][3]==12&&dl[i][4]==179) break;
    //printf("%d\n",i);
    scanf("%lld",&n);
    fo(i,1,tail){
        if (dl[i][4]>n) continue;
        if (dl[i][0]==dl[i][1]||dl[i][1]==dl[i][2]||dl[i][2]==dl[i][3]||dl[i][3]==dl[i][4]) continue;
        ++top;
        ans[top].a=dl[i][0];ans[top].b=dl[i][1];
        ans[top].c=dl[i][2];ans[top].d=dl[i][3];
        ans[top].e=dl[i][4];
    }
    if (!top) printf("No Solution\n");
    else{
        sort(ans+1,ans+top+1,cmp);
        printf("%d\n",top);
        fo(i,1,top) printf("%lld %lld %lld %lld %lld\n",ans[i].a,ans[i].b,ans[i].c,ans[i].d,ans[i].e);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值