So I am trying to calculate this formula but the results are strange. The elements are extremely large so I am not sure where I went wrong. I have attached a photo of the formula:
and here is my code:
*calculating mu_sum and sigma_sum;
T_hat=180;
mu_sum_first_part={0,0,0,0};
mu_sum_second_part={0,0,0,0};
mu_sum={0,0,0,0};
*calculating mu_sum;
do i = 0 to T_hat;
term=(T_hat - i)*(B0**i)*a;
mu_sum_first_part = mu_sum_first_part + term;
end;
do i=1 to T_hat;
term =B0**i;
mu_sum_second_part = mu_sum_second_part + term;
end;
mu_sum = mu_sum_first_part + mu_sum_second_part*zt;
print mu_sum;
*calculating sigma_sum;
term=I(4);
sigma_sum=sigma;
do j=1 to T_hat;
term = term + B0**j;
sigma_sum = sigma_sum + (term*sigma*(term`));
end;
print sigma_sum;
I know this is long but please help!!
First thing that jumps out at me is your loop first term in mu has 1 too many:
do i = 0 to T_hat;
term=(T_hat - i)*(B0**i)*a;
mu_sum_first_part = mu_sum_first_part + term;
end;
Should be:
do i = 0 to T_hat-1;
term=(T_hat - i)*(B0**i)*a;
mu_sum_first_part = mu_sum_first_part + term;
end;
There is nothing mathematically wrong with your program. When you are raising a matrix to the 180th power, you should not be surprised to see very large or very small values. For example, if you let
B0 = {
0 1 0 0,
0 0 1 0,
0 0 0 1,
0 1 1 1
};
then elements of B0**T are O( 1E47 ). If you divide B0 by 2 and raise the result to the 180th power, then the elements are O( 1E-8 ).
Presumably these formulas are intended for matrices B0 that have a special structure, such as ||B0**n|| --> 0 as n --> infinity. Otherwise the power series won't converge. I suggest you double-check that the B0 you are using satisfies the assumptions of the reference.
You didn't ask about efficiency, but you would be wise to compute the truncated power series by using Horner's method in SAS/IML, rather than explicitly forming powers of B0.
Here the question
At the Infinite House of Pancakes, there are only finitely many pancakes, but there are infinitely many diners who would be willing to eat them! When the restaurant opens for breakfast, among the infinitely many diners, exactly D have non-empty plates; the ith of these has Pi pancakes on his or her plate. Everyone else has an empty plate.
Normally, every minute, every diner with a non-empty plate will eat one pancake from his or her plate. However, some minutes may be special. In a special minute, the head server asks for the diners' attention, chooses a diner with a non-empty plate, and carefully lifts some number of pancakes off of that diner's plate and moves those pancakes onto one other diner's (empty or non-empty) plate. No diners eat during a special minute, because it would be rude.
You are the head server on duty this morning, and it is your job to decide which minutes, if any, will be special, and which pancakes will move where. That is, every minute, you can decide to either do nothing and let the diners eat, or declare a special minute and interrupt the diners to make a single movement of one or more pancakes, as described above.
Breakfast ends when there are no more pancakes left to eat. How quickly can you make that happen?
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each consists of one line with D, the number of diners with non-empty plates, followed by another line with D space-separated integers representing the numbers of pancakes on those diners' plates.
Output
For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is the smallest number of minutes needed to finish the breakfast.
Limits
1 ≤ T ≤ 100.
Small dataset
1 ≤ D ≤ 6.
1 ≤ Pi ≤ 9.
Large dataset
1 ≤ D ≤ 1000.
1 ≤ Pi ≤ 1000.
Sample
Input
3
1
3
4
1 2 1 2
1
4
Output
Case #1: 3
Case #2: 2
Case #3: 3
and this is my source code
int result = 0, D = 0;
int part(vector<int> v1) {
if(v1[D - 1] == 0)
return 0;
int t1 = 0, t2 = 0, t3 = 0, i = 0;
vector<int> v2;
for(i = 0; i < D; ++i)
if(v1[i])
v2.push_back(v1[i] - 1);
else
v2.push_back(0);
if(v1[D - 1] == 1)
v1[D - 1] = 0;
else if( v1[D-1] % 2 )
v1[ D- 1 ] = ( v1[D-1] / 2 ) + 1;
else
v1[ D -1 ] = v1[ D - 1 ] / 2;
sort(v1.begin(),v1.end());
t1 = 1 + part(v1);
t2 = 1 + part(v2);
t3 = min(t1,t2);
return t3;
}
int main(void) {
int T = 0, count = 0;
scanf("%d",&T);
while(T--) {
vector<int> v1;
vector<int> ::iterator it;
int i = 0, temp = 0; D = 0;
result = 0;
++count;
scanf("%d",&D);
for(i = 0; i < D; ++i) {
scanf("%d",&temp);
v1.push_back(temp);
}
sort( v1.begin(), v1.end() );
result = part(v1);
printf("Case #%d: %d\n",count,result);
}
return 0;
}
I have this program that is supposed to search for perfect numbers.
(X is a perfect number if the sum of all numbers that divide X, divided by 2 is equal to X)
sum/2 = x
Now It has found the first four, which were known in Ancient Greece, so it's not really a anything awesome.
The next one should be 33550336.
I know it is a big number, but the program has been going for about 50 minutes, and still hasn't found 33550336.
Is it because I opened the .txt file where I store all the perfect numbers while the program was running, or is it because I don't have a PC fast enough to run it*, or because I'm using Python?
*NOTE: This same PC factorized 500 000 in 10 minutes (while also running the perfect number program and Google Chrome with 3 YouTube tabs), also using Python.
Here is the code to the program:
i = 2
a = open("perfect.txt", 'w')
a.close()
while True:
sum = 0
for x in range(1, i+1):
if i%x == 0:
sum += x
if sum / 2 == i:
a = open("perfect.txt", 'a')
a.write(str(i) + "\n")
a.close()
i += 1
The next one should be 33550336.
Your code (I fixed the indentation so that it does in principle what you want):
i = 2
a = open("perfect.txt", 'w')
a.close()
while True:
sum = 0
for x in range(1, i+1):
if i%x == 0:
sum += x
if sum / 2 == i:
a = open("perfect.txt", 'a')
a.write(str(i) + "\n")
a.close()
i += 1
does i divisions to find the divisors of i.
So to find the perfect numbers up to n, it does
2 + 3 + 4 + ... + (n-1) + n = n*(n+1)/2 - 1
divisions in the for loop.
Now, for n = 33550336, that would be
Prelude> 33550336 * (33550336 + 1) `quot` 2 - 1
562812539631615
roughly 5.6 * 1014 divisions.
Assuming your CPU could do 109 divisions per second (it most likely can't, 108 is a better estimate in my experience, but even that is for machine ints in C), that would take about 560,000 seconds. One day has 86400 seconds, so that would be roughly six and a half days (more than two months with the 108 estimate).
Your algorithm is just too slow to reach that in reasonable time.
If you don't want to use number-theory (even perfect numbers have a very simple structure, and if there are any odd perfect numbers, those are necessarily huge), you can still do better by dividing only up to the square root to find the divisors,
i = 2
a = open("perfect.txt", 'w')
a.close()
while True:
sum = 1
root = int(i**0.5)
for x in range(2, root+1):
if i%x == 0:
sum += x + i/x
if i == root*root:
sum -= x # if i is a square, we have counted the square root twice
if sum == i:
a = open("perfect.txt", 'a')
a.write(str(i) + "\n")
a.close()
i += 1
that only needs about 1.3 * 1011 divisions and should find the fifth perfect number in a couple of hours.
Without resorting to the explicit formula for even perfect numbers (2^(p-1) * (2^p - 1) for primes p such that 2^p - 1 is prime), you can speed it up somewhat by finding the prime factorisation of i and computing the divisor sum from that. That will make the test faster for all composite numbers, and much faster for most,
def factorisation(n):
facts = []
multiplicity = 0
while n%2 == 0:
multiplicity += 1
n = n // 2
if multiplicity > 0:
facts.append((2,multiplicity))
d = 3
while d*d <= n:
if n % d == 0:
multiplicity = 0
while n % d == 0:
multiplicity += 1
n = n // d
facts.append((d,multiplicity))
d += 2
if n > 1:
facts.append((n,1))
return facts
def divisorSum(n):
f = factorisation(n)
sum = 1
for (p,e) in f:
sum *= (p**(e+1) - 1)/(p-1)
return sum
def isPerfect(n):
return divisorSum(n) == 2*n
i = 2
count = 0
out = 10000
while count < 5:
if isPerfect(i):
print i
count += 1
if i == out:
print "At",i
out *= 5
i += 1
would take an estimated 40 minutes on my machine.
Not a bad estimate:
$ time python fastperf.py
6
28
496
8128
33550336
real 36m4.595s
user 36m2.001s
sys 0m0.453s
It is very hard to try and deduce why this has happened. I would suggest that you run your program either under a debugger and test several iteration manually to check if the code is really correct (I know you have already calculated 4 numbers but still). Alternatively it would be good to run your program under a python profiler just to see if it hasn't accidentally blocked on a lock or something.
It is possible, but not likely that this is an issue related to you opening the file while it is running. If it was an issue, there would have probably been some error message and/or program close/crash.
I would edit the program to write a log-type output to a file every so often. For example, everytime you have processed a target number that is an even multiple of 1-Million, write (open-append-close) the date-time and current-number and last-success-number to a log file.
You could then Type the file once in a while to measure progress.
The “Narcissistic numbers”, are n digit numbers where the sum of all the nth power of their digits is equal to the number.
So, 153 is a narcissistic number because 1^3 + 5^3 + 3^3 = 153.
Now given N, find all Narcissistic numbers that are N digit length ?
My Approach : was to iterate over all numbers doing sum of powers of digits
and check if its the same number or not, and I per calculated the powers.
but that's not good enough, so is there any faster way ?!
Update:
In nature there is just 88 narcissistic numbers, and the largest is 39 digits long,
But I just need the numbers with length 12 or less.
My Code :
long long int powers[11][12];
// powers[x][y] is x^y. and its already calculated
bool isNarcissistic(long long int x,int n){
long long int r = x;
long long int sum = 0;
for(int i=0; i<n ; ++i){
sum += powers[x%10][n];
if(sum > r)
return false;
x /= 10;
}
return (sum == r);
}
void find(int n,vector<long long int> &vv){
long long int start = powers[10][n-1];
long long int end = powers[10][n];
for(long long int i=start ; i<end ; ++i){
if(isNarcissistic(i,n))
vv.push_back(i);
}
}
Since there are only 88 narcisstic numbers in total, you can just store them in a look up table and iterate over it: http://mathworld.wolfram.com/NarcissisticNumber.html
Start from the other end. Iterate over the set of all nondecreasing sequences of d digits, compute the sum of the d-th powers, and check whether that produces (after sorting) the sequence you started with.
Since there are
9×10^(d-1)
d-digit numbers, but only
(10+d-1) `choose` d
nondecreasing sequences of d digits, that reduces the search space by a factor close to d!.
The code below implements the idea of #Daniel Fischer. It duplicates the table referenced at Mathworld and then prints a few more 11-digit numbers and verifies that there are none with 12 digits as stated here.
It would actually be simplier and probably a little faster to generate all possible histograms of non-increasing digit strings rather than the strings themselves. By a histogram I mean a table indexed 0-9 of frequencies of the respective digit. These can be compared directly without sorting. But the code below runs in < 1 sec, so I'm not going to implement the histogram idea.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_DIGITS 12
// pwr[d][n] is d^n
long long pwr[10][MAX_DIGITS + 1];
// Digits and final index of number being considered.
int digits[MAX_DIGITS];
int m;
// Fill pwr.
void fill_tbls(void)
{
for (int d = 0; d < 10; d++) {
pwr[d][0] = 1;
for (int p = 1; p <= MAX_DIGITS; p++)
pwr[d][p] = pwr[d][p-1] * d;
}
}
// qsort comparison for integers descending
int cmp_ints_desc(const void *vpa, const void *vpb)
{
const int *pa = vpa, *pb = vpb;
return *pb - *pa;
}
// Test current number and print if narcissistic.
void test(void)
{
long long sum = 0;
for (int i = 0; i <= m; i++)
sum += pwr[digits[i]][m + 1];
int sum_digits[MAX_DIGITS * 2];
int n = 0;
for (long long s = sum; s; s /= 10)
sum_digits[n++] = s % 10;
if (n == m + 1) {
qsort(sum_digits, n, sizeof(int), cmp_ints_desc);
if (memcmp(sum_digits, digits, n * sizeof(int)) == 0)
printf("%lld\n", sum);
}
}
// Recursive generator of non-increasing digit strings.
// Calls test when a string is complete.
void gen(int i, int min, int max)
{
if (i > m)
test();
else {
for (int d = min; d <= max; d++) {
digits[i] = d;
gen(i + 1, 0, d);
}
}
}
// Fill tables and generate.
int main(void)
{
fill_tbls();
for (m = 0; m < MAX_DIGITS; m++)
gen(0, 1, 9);
return 0;
}
I wrote a program in Lua which found all the narcissistic numbers in 30829.642 seconds. The basis of the program is a recursive digit-value count array generator function which calls a checking function when it's generated the digit-value count for all the digit-values. Each nested loop iterates:
FROM i=
The larger of 0 and the solution to a+x*d^o+(s-x)*(d-1)^o >= 10^(o-1) for x
where
- 'a' is the accumulative sum of powers of digits so far,
- 'd' is the current digit-value (0-9 for base 10),
- 'o' is the total number of digits (which the sum of the digit-value count array must add up to),
- 's' represents the remaining slots available until the array adds to 'o'
UP TO i<=
The smaller of 's' and the solution to a+x*d^o < 10^o for x with the same variables.
This ensures that the numbers checked will ALWAYS have the same number of digits as 'o', and therefore be more likely to be narcissistic while avoiding unnecessary computation.
In the loop, it does the recursive call for which it decrements the digit-value 'd' adds the current digit-value's contribution (a=a+i*d^o) and takes the i digit-slots used up away from 's'.
The gist of what I wrote is:
local function search(o,d,s,a,...) --Original number of digits, digit-value, remaining digits, accumulative sum, number of each digit-value in descending order (such as 5 nines)
if d>0 then
local d0,d1=d^o,(d-1)^o
local dd=d0-d1
--a+x*d^o+(s-x)*(d-1)^o >= 10^(o-1) , a+x*d^o < 10^o
for i=max(0,floor((10^(o-1)-s*d1-a)/dd)),min(s,ceil((10^o-a)/dd)-1) do
search(o,d-1,s-i,a+i*d0,i,...) --The digit counts are passed down as extra arguments.
end
else
--Check, with the count of zeroes set to 's', if the sum 'a' has the same count of each digit-value as the list specifies, and if so, add it to a list of narcissists.
end
end
local digits=1 --Skip the trivial single digit narcissistic numbers.
while #found<89 do
digits=digits+1
search(digits,9,digits,0)
end
EDIT: I forgot to mention that my program finds 89 narcissistic numbers! These are what it finds:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208, 9474, 54748, 92727, 93084, 548834, 1741725, 4210818, 9800817, 9926315, 24678050, 24678051, 88593477, 146511208, 472335975, 534494836, 912985153, 4679307774, 32164049650, 32164049651, 40028394225, 42678290603, 44708635679, 49388550606, 82693916578, 94204591914, 28116440335967, 4338281769391370, 4338281769391371, 21897142587612075, 35641594208964132, 35875699062250035, 1517841543307505039, 3289582984443187032, 4498128791164624869, 4929273885928088826, 63105425988599693916, 128468643043731391252,449177399146038697307, 21887696841122916288858, 27879694893054074471405, 27907865009977052567814, 28361281321319229463398, 35452590104031691935943, 174088005938065293023722, 188451485447897896036875, 239313664430041569350093, 1550475334214501539088894, 1553242162893771850669378, 3706907995955475988644380, 3706907995955475988644381, 4422095118095899619457938, 121204998563613372405438066, 121270696006801314328439376, 128851796696487777842012787, 174650464499531377631639254, 177265453171792792366489765, 14607640612971980372614873089, 19008174136254279995012734740, 19008174136254279995012734741, 23866716435523975980390369295, 1145037275765491025924292050346, 1927890457142960697580636236639, 2309092682616190307509695338915, 17333509997782249308725103962772, 186709961001538790100634132976990, 186709961001538790100634132976991, 1122763285329372541592822900204593, 12639369517103790328947807201478392, 12679937780272278566303885594196922, 1219167219625434121569735803609966019, 12815792078366059955099770545296129367, 115132219018763992565095597973971522400, 115132219018763992565095597973971522401
For posterity ;-) This is most similar to #Krakow10's approach, generating bags of digits recursively, starting with 9, then 8, then 7 ... to 0.
It's Python3 code and finds all base-10 solutions with 1 through 61 digits (the first "obviously impossible" width) in less than 10 minutes (on my box). It's by far the fastest code I've ever heard of for this problem. What's the trick? No trick - just tedium ;-) As we go along, the partial sum so far yields a world of constraints on feasible continuations. The code just pays attention to those, and so is able to cut off vast masses of searches early.
Note: this doesn't find 0. I don't care. While all the references say there are 88 solutions, their tables all have 89 entries. Some eager editor must have added "0" later, and then everyone else mindlessly copied it ;-)
EDIT New version is over twice as fast, by exploiting some partial-sum constraints earlier in the search - now finishes in a little over 4 minutes on my box.
def nar(width):
from decimal import Decimal as D
import decimal
decimal.getcontext().prec = width + 10
if width * 9**width < 10**(width - 1):
raise ValueError("impossible at %d" % width)
pows = [D(i) ** width for i in range(10)]
mintotal, maxtotal = D(10)**(width - 1), D(10)**width - 1
def extend(d, todo, total):
# assert d > 0
powd = pows[d]
d1 = d-1
powd1 = pows[d1]
L = total + powd1 * todo # largest possible taking no d's
dL = powd - powd1 # the change to L when i goes up 1
for i in range(todo + 1):
if i:
total += powd
todo -= 1
L += dL
digitcount[d] += 1
if total > maxtotal:
break
if L < mintotal:
continue
if total < mintotal or L > maxtotal:
yield from extend(d1, todo, total)
continue
# assert mintotal <= total <= L <= maxtotal
t1 = total.as_tuple().digits
t2 = L.as_tuple().digits
# assert len(t1) == len(t2) == width
# Every possible continuation has sum between total and
# L, and has a full-width sum. So if total and L have
# some identical leading digits, a solution must include
# all such leading digits. Count them.
c = [0] * 10
for a, b in zip(t1, t2):
if a == b:
c[a] += 1
else:
break
else: # the tuples are identical
# assert d == 1 or todo == 0
# assert total == L
# This is the only sum we can get - no point to
# recursing. It's a solution iff each digit has been
# picked exactly as many times as it appears in the
# sum.
# If todo is 0, we've picked all the digits.
# Else todo > 0, and d must be 1: all remaining
# digits must be 0.
digitcount[0] += todo
# assert sum(c) == sum(digitcount) == width
if digitcount == c:
yield total
digitcount[0] -= todo
continue
# The tuples aren't identical, but may have leading digits
# in common. If, e.g., "9892" is a common prefix, then to
# get a solution we must pick at least one 8, at least two
# 9s, and at least one 2.
if any(digitcount[j] < c[j] for j in range(d, 10)):
# we're done picking digits >= d, but don't have
# enough of them
continue
# for digits < d, force as many as we need for the prefix
newtodo, newtotal = todo, total
added = []
for j in range(d):
need = c[j] - digitcount[j]
# assert need >= 0
if need:
newtodo -= need
added.append((j, need))
if newtodo < 0:
continue
for j, need in added:
newtotal += pows[j] * need
digitcount[j] += need
yield from extend(d1, newtodo, newtotal)
for j, need in added:
digitcount[j] -= need
digitcount[d] -= i
digitcount = [0] * 10
yield from extend(9, width, D(0))
assert all(i == 0 for i in digitcount)
if __name__ == "__main__":
from datetime import datetime
start_t = datetime.now()
width = total = 0
while True:
this_t = datetime.now()
width += 1
print("\nwidth", width)
for t in nar(width):
print(" ", t)
total += 1
end_t = datetime.now()
print(end_t - this_t, end_t - start_t, total)
I think the idea is to generate similar numbers. For example, 61 is similar to 16 as you are just summing
6^n +1^n
so
6^n+1^n=1^n+6^n
In this way you can reduce significant amount of numbers. For example in 3 digits scenario,
121==112==211,
you get the point. You need to generate those numbers first.
And you need to generate those numbers without actually iterating from 0-n.
Python version is:
def generate_power_list(power):
return [i**power for i in range(0,10)]
def find_narcissistic_numbers_naive(min_length, max_length):
for number_length in range(min_length, max_length):
power_dict = generate_power_dictionary(number_length)
max_number = 10 ** number_length
number = 10** (number_length -1)
while number < max_number:
value = 0
for digit in str(number):
value += power_dict[digit]
if value == number:
logging.debug('narcissistic %s ' % number)
number += 1
Recursive solution:
In this solution each recursion handles a single digit of the array of digits being used, and tries all appropriate combinations of that digit
def execute_recursive(digits, number_length):
index = len(digits)
if digits:
number = digits[-1]
else:
number = 0
results = []
digits.append(number)
if len(digits) < number_length:
while number < 10:
results += execute_recursive(digits[:], number_length)
number += 1
digits[index] = number
else:
while number < 10:
digit_value = sum_digits(digits)
if check_numbers_match_group(digit_value, digits):
results.append(digit_value)
logging.debug(digit_value)
number += 1
digits[index] = number
return results
def find_narcissistic_numbers(min_length, max_length):
for number_length in range(min_length, max_length):
digits = []
t_start = time.clock()
results = execute_recursive(digits, number_length)
print 'duration: %s for number length: %s' %(time.clock() - t_start, number_length)
Narcissistic number check
In the base version, when checking that a number matched the digits, we iterated through each digit type, to ensure that there were the same number of each type. In this version we have added the optimisation of checking the digit length is correct before doing the full check.
I expected that this would have more of an effect on small number lengths, because as number length increases, there will tend to be more numbers in the middle of the distribution. This was somewhat upheld by the results:
n=16: 11.5% improvement
n=19: 9.8% improvement
def check_numbers_match_group(number, digits):
number_search = str(number)
# new in v1.3
if len(number_search) != len(digits):
return False
for digit in digit_list:
if number_search.count(digit[0]) != digits.count(digit[1]):
return False
return True
I think you could use Multinomial theorem for some optimisation of cheacking if it is Narcissistic number.
you can calculate (a+b+c+..)^n- sum of non n-th powers values
for example for n=2 you should compare x and (a+b)^2-2*a*b where a and b is digits of number x
'''We can use Nar() function to calculate the Narcissitic Number.'''
import math
def Nar(num):
sum=0
n=len(str(num))
while n>0:
temp=num%10
sum=sum+math.pow(temp,n)
num=num/10
return sum
x=input()
y=Nar(x)
if x==y:
print x,' is a Narcissistic number'
else:
print x,' is not a Narcissistic number'