一个N位的十进制正整数,如果它的每个位上的数字的N次方的和等于这个数本身,则称其为花朵数。
例如:
当N=3时,153就满足条件,因为 1^3 + 5^3 + 3^3 = 153,这样的数字也被称为水仙花数(其中,“^”表示乘方,5^3表示5的3次方,也就是立方)。
当N=4时,1634满足条件,因为 1^4 + 6^4 + 3^4 + 4^4 = 1634。
当N=5时,92727满足条件。
实际上,对N的每个取值,可能有多个数字满足条件。
程序的任务是:求N=21时,所有满足条件的花朵数。注意:这个整数有21位,它的各个位数字的21次方之和正好等于这个数本身。
如果满足条件的数字不只有一个,请从小到大输出所有符合条件的数字,每个数字占一行。因为这个数字很大,请注意解法时间上的可行性。要求程序在3分钟内运行完毕。
【程序运行参考结果】
128468643043731391252
449177399146038697307
本题的思路:
1:关键是:去掉所含0-9数字个数相同的21位数,以免重复运算,增加时间,比如123456789012345678901与987654321098765432101与987654321012345678901中的所含数字的个数都是相同的,所以其每一位的21次方的和都相等,将所得的21次方和 从大到小进行排序,若对应的数与原数不相等,则都不成立,因此若不去掉重复的数,将会增加运算时间;
例如:
当N=3时,153就满足条件,因为 1^3 + 5^3 + 3^3 = 153,这样的数字也被称为水仙花数(其中,“^”表示乘方,5^3表示5的3次方,也就是立方)。
当N=4时,1634满足条件,因为 1^4 + 6^4 + 3^4 + 4^4 = 1634。
当N=5时,92727满足条件。
实际上,对N的每个取值,可能有多个数字满足条件。
程序的任务是:求N=21时,所有满足条件的花朵数。注意:这个整数有21位,它的各个位数字的21次方之和正好等于这个数本身。
如果满足条件的数字不只有一个,请从小到大输出所有符合条件的数字,每个数字占一行。因为这个数字很大,请注意解法时间上的可行性。要求程序在3分钟内运行完毕。
【程序运行参考结果】
128468643043731391252
449177399146038697307
本题的思路:
1:关键是:去掉所含0-9数字个数相同的21位数,以免重复运算,增加时间,比如123456789012345678901与987654321098765432101与987654321012345678901中的所含数字的个数都是相同的,所以其每一位的21次方的和都相等,将所得的21次方和 从大到小进行排序,若对应的数与原数不相等,则都不成立,因此若不去掉重复的数,将会增加运算时间;
2:以为要将每一位数的21次方之和从大到小排序,所以运算从21个9这个最大数开始向下运算,又因为10个9的21次方之和超过了21位数,所以从9个9,12个8开始一次往下运算即可,这样又可以节约一部分时间。
#include "iostream"
#include "string.h"
#define N 21
using namespace std;
int a[10][N+1]; //记录每个数的21次方是多少
int book[10]; //记录每个数多少个
int flag[10]; //标记每个数21次方的最高位
int sum[10][N+1]; //计算每个数的book[i]个和
int result[N+1]; //总和
bool X(int where,int num);
void handle(); //清理
bool add();
void test(); //检验
int main(){
handle();
void first(); //初始化每个数的N次方
void dfs(int k,int sum);
first();
dfs(0,21);
return 0;
}
void first(){
int i,temp,j,k;
//i 枚举0-9
for(i=0;i<10;i++)//对0-9每个数的21次方 分别存入数组a[i][N+1]中
{
a[i][0]=1; //初始第一位要为1
for(k=0;k<N;k++) //枚举21次方
{
temp=0; //上一个数的进位
for(j=0;j<N;j++) //枚举第几位数
{
int now=temp+a[i][j]*i; //上一位的进位+该位
a[i][j]=now%10; //该位
temp=now/10; //进位
}
}
}
//输出测试
/* for(i=0;i<=9;i++)
{
for(j=N-1;j>=0;j--)
cout<<a[i][j];
cout<<endl;
}*/
}
//求每个数字可以为几个 k
void dfs(int k,int sum){ //sum还有几个 k第几个
if(sum==0){
test();
return;
}
if(k==9){
book[k]=sum;
dfs(k+1,0);
return;
}
int i;
for(i=0;i<=sum;i++)
{
book[k]=i;
dfs(k+1,sum-i);
book[k]=0;
}
}
void test(){
if(book[9]>9||book[8]>11)
return;
int i;
for(i=0;i<=9;i++){ //相乘
if(X(i,book[i])==0){
handle();
return;
}
}
//相加
if(add()==0) {
handle();
return;
}
int f[10];
for(i=0;i<=9;i++) //初始化检验数组
f[i]=0;
for(i=0;i<N;i++){ //检测每位结果
f[result[i]]++;
}
for(i=0;i<=9;i++){
if(f[i]!=book[i])
{
handle();
return;
}
}
for(i=N-1;i>=0;i--)
cout<<result[i];
cout<<endl;
}
bool add(){
int i,j,temp;
for(i=1;i<=9;i++) //0-9 sum
{
temp=0;
for(j=0;j<=N;j++){
int now=temp+sum[i][j]+result[j];
result[j]=now%10;
temp=now/10;
}
}
if(result[N]>0||result[N-1]==0)
return false;
else
return true;
}
bool X(int where,int num){ //每个数有几个 相乘
int i;
int temp=0;
for(i=0;i<=N;i++) //21位
{
int now=temp+a[where][i]*num;
sum[where][i]=now%10;
temp=now/10;
}
if(sum[where][N]>0)
return false;
else
return true;
}
void handle(){
memset(result,0,sizeof(result));
memset(sum,0,sizeof(sum));
}