51nod 1139 奇妙等式的解

本文探讨了一种奇妙的数学等式a^2 + b^2 + c^2 + d^2 + e^2 = abcde,其中a < b < c < d < e。当给定数N时,寻找所有满足e <= N的解。通过数学变换和解的构造,可以由一组解生成更多的解,使用暴力构造法和哈希判断避免重复,以快速找到所有满足条件的解。注意,输出时需确保a<b<c<d<e。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

输入

输入1个数N(0 <= N <= 10^18)。

输出

第1行:1个数N,N为解的数量。
第2 - N + 1行:每行5个数,中间用空格分隔,对应a,b,c,d,e。解按照a,b,c,d,e依次排序。如果无解,输出No Solution。

输入样例

200

输出样例

2
1 3 4 9 107
1 3 5 12 179

感觉很棘手。尝试能否通过一组解来构造另一组解(最小的一组解不大)。 
a2+b2+c2+d2+e2=abcde⇒b2+c2+d2+e2=abcde−a2a2+b2+c2+d2+e2=abcde⇒b2+c2+d2+e2=abcde−a2。 
尝试替换一个数,将aa替换为a′a′。 
a′2+b2+c2+d2+e2=a′bcdea′2+b2+c2+d2+e2=a′bcde 
于是有a′2+abcde−a2=a′bcde⇒a′2+abcde−a2=a′bcde⇒ 
a′2−a2=bcde(a′−a)⇒(a′+a)(a′−a)=bcde(a′−a)⇒a′2−a2=bcde(a′−a)⇒(a′+a)(a′−a)=bcde(a′−a)⇒ 
a′+a=bcde⇒a′=bcde−aa′+a=bcde⇒a′=bcde−a 
所以,若a,b,c,d,e是一组解,则 
bcde-a,b,c,d,e/a,acde-b,c,d,e…也是满足式子①。 
然后就可以根据某一组a,b,c,d,e暴力构造出所有答案。 
我也不知道为什么跑这么快。 
还有个问题。必须满足a<b<c<d<ea<b<c<d<e,所以输出的时候只输出满足a<b<c<d<ea<b<c<d<e的。 
不要在暴力过程中将不满足a<b<c<d<ea<b<c<d<e的删去,因为通过这样的a,b,c,d,e,仍然可以构造出满足a<b<c<d<ea<b<c<d<e的a,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);
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值