A PDDI is a number such the the sum of all the digits raised to themselves is equal to the number itself.
For example, 3435 = (3^3) + (4^4) + (3^3) + (5^5)
The code below takes too long to check for PDDIs between one to a huge number. Is there any way to make it faster?
System.out.print("Enter the number");
Scanner s = new Scanner(System.in);
int n = s.nextInt();
int m = 0, sum = 0, k = 0;
// We're going to try all integers between one to n.
for(int i = 1; i<=n; i++){
sum = 0;
m = i;
while(m>0){
k = m % 10;
sum = sum + (int)Math.pow(k, k);
m = m/10;
}
if(i == sum)
System.out.println(i);
}
The number from 0 to 9 to the power of 2 can be precalculated and kept in a an array.
int powered [] = new int [10];
powered[0] = 0;
powered[1] = 1;
powered[2] = 4;
..
powered[9] = 81;
Then for each digit fech the powered number using the digit as an index to the powered array.
For example 234
would be powered[2] + powered[3] + powered[4]
This will save some math operations.
Also you could think of a multithreaded approach having N threads doing the calculations for different numbers in parallel.
Since you are using only power from 0 to 9, you could cache these values in a int[]
instead of computing Math.pow(k, k)
everytime. It won't improve that much but, it's a start.
int[] pows = new int[] {0, 1, 4, 27, 256, 3125, 46656, 823543, 16777216, 387420489 };
for (int i = 0; i < 10; ++i) {
pows[i] = (int) Math.pow(i, i);
}
System.out.print("Enter the number");
Scanner s = new Scanner(System.in);
int n = s.nextInt();
int m = 0, sum = 0, k = 0;
// We're going to try all integers between one to n.
for(int i = 1, i<=n, i++){
sum = 0;
m = i;
while(m>0){
k = m % 10;
sum = sum + pows[k]; // use cached values here
m = m/10;
}
if(i == sum)
System.out.println(i);
}
Based on logic you may skip some iterations. Lets take the number 281
as an example, which gives 4 + 16777216 + 1 = 16777251
, the result is above 281, so theres no changes that 282, 283, 284, ... 289 gives a number equals to 281. In such cases you may want to skip these useless iterations by manually incrementing i
.
int[] pows = new int [10];
for (int i = 0; i < 10; ++i) {
pows[i] = (int) Math.pow(i, i);
}
System.out.print("Enter the number");
Scanner s = new Scanner(System.in);
int n = s.nextInt();
int m = 0, sum = 0, k = 0, lastNumberDigit;
// We're going to try all integers between one to n.
for(int i = 1, i<=n, i++){
sum = 0;
m = i;
while(m>0){
lastNumberDigit = m; // on the last iteration, we'll get the last digit
k = m % 10;
sum = sum + pows[k]; // use cached values here
m = m/10;
}
if(i == sum) {
System.out.println(i);
} else if (sum > i) {
i += (10 - lastNumberDigit - 1); // jump to the next decade (-1 because the for will apply i++ on it)
}
}
I used this logic on decade, but you may want to extend it to hundreds or even more, but it will be much more tricky.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.