Perfect Squares - Can someone explain following math? - c

Problem Statement:
Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.
Example 1:
Input: n = 12
Output: 3
Explanation: 12 = 4 + 4 + 4.
Example 2:
Input: n = 13
Output: 2
Explanation: 13 = 4 + 9.
Using the following knowledge about squares (given below) we can implement the following solution.
A natural number is...
... a square if and only if each prime factor occurs to an even power in the number's prime factorization.
... a sum of two squares if and only if each prime factor that's 3 modulo 4 occurs to an even power in the number's prime factorization.
... a sum of three squares if and only if it's not of the form 4a(8b+7) with integers a and b.
... a sum of four squares. Period. No condition. You never need more than four.
int numSquares(int n) {
while (n % 4 == 0)
n /= 4;
if (n % 8 == 7)
return 4;
for (int a=0; a*a<=n; ++a) {
int b = sqrt(n - a*a);
if (a*a + b*b == n)
return 1 + !!a;
}
return 3;
}
Question:
Can someone help me understand what exactly are we trying to achieve in following for loop?
I'm a little lost here.
for (int a=0; a*a<=n; ++a) {
int b = sqrt(n - a*a);
if (a*a + b*b == n)
return 1 + !!a;
}

The loop is trying to find two squares that sum to n.
Rather than trying every combination of numbers to see if we can square them and they add up to n, we just loop through the possibilities for one of the numbers -- this is a. We square that with a*a, and subtract that from n. We then get the integer part of the square root of this difference, and this is b. If a2+b2 adds up to n, this is the pair of squares that we're looking for.
We need to calculate the sum of the squares in case n - a*a wasn't a perfect square. In that case its square root will have a fraction in it, which will be lost when we convert it to an integer. In other words, testing a*a+b*b == n allows us to determine whether the square root was an integer.

Related

Given a range find the sum of number that is divisible by 3 or 5

The below code that works perfectly fine for smaller digits, But Time dilation for greater digits
given me the suggestion
#include<stdio.h>
int main()
{
int num;
int sum=0;
scanf("%d",&num);
for(int i=1;i<=num;i++)
{
if(i%3==0 || i%5==0)
sum += i;
}
printf("%d",sum);
}
Need efficient code for this
Try to reduce the time take for the code.
The answer can be computed with simple arithmetic without any iteration. Many Project Euler questions are intended to make you think about clever ways to find solutions without just using the raw power of computers to chug through calculations. (This was Project Euler question 1, except the Project Euler problem specifies the limit using less than instead of less than or equal to.)
Given positive integers N and F, the number of positive multiples of F that are less than or equal to N is ⌊N/F⌋. (⌊x⌋ is the greatest integer not greater than x.) For example, the number of multiples of 5 less than or equal to 999 is ⌊999/5⌋ = ⌊199.8⌋ = 199.
Let n be this number of multiples, ⌊N/F⌋.
The first multiple is F and the last multiple is n•F. For example, with 1000 and 5, the first multiple is 5 and the last multiple is 200•5 = 1000.
The multiples are evenly spaced, so the average of all of them equals the average of the first and the last, so it is (F + nF)/2.
The total of the multiples equals their average multiplied by the number of them, so the total of the multiples of F less than N is n • (F + n•F)/2.
Adding the sum of multiples of 3 and the sum of multiples of 5 includes the multiples of both 3 and 5 twice. We can correct for this by subtracting the sum of those numbers. Multiples of both 3 and 5 are multiples of 15.
Thus, we can compute the requested sum using simple arithmetic without any iteration:
#include <stdio.h>
static long SumOfMultiples(long N, long F)
{
long NumberOfMultiples = N / F;
long FirstMultiple = F;
long LastMultiple = NumberOfMultiples * F;
return NumberOfMultiples * (FirstMultiple + LastMultiple) / 2;
}
int main(void)
{
long N = 1000;
long Sum = SumOfMultiples(N, 3) + SumOfMultiples(N, 5) - SumOfMultiples(N, 3*5);
printf("%ld\n", Sum);
}
As you do other Project Euler questions, you should look for similar ideas.

Why I am not getting any output here?

In project Euler there is a problem titled Smallest Multiple. I tried to solve it and try to write a code for that problem. But I didn't get any output!
The problem is described below:
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
So I write code for this problem. First of all I write a code to check whether it's correct or not that 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. For that problem I write the below program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main()
{
int i,j,count = 0,num;
for (i = 1; count != 10; i++) {
count = 0;
for (j = 1; j <= 10; j++)
if(!(i % j))
count++;
if( count == 10 )
num = i;
}
printf("%d\n",num);
}
and I get the desirable output for this problem. But whenever I write this code for finding the value which is divisible by 1-20 without any remainder then I didn't find any output. I wrote the below code and compile and run but it didn't give me any result. But the programme is still running and whenever I press Control+C then the program is terminated.
The code for the problem.....
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int main()
{
long long int i,j,count = 0,num;
for (i = 1; count != 20; i++) {
count = 0;
for (j = 1; j <= 20; j++)
if (!( i % j))
count++;
if (count == 20)
num = i;
}
printf("%lld\n",num);
}
So where is the problem?
If I were going to do this, I'd do it somewhat differently. Let's start by thinking about a number that isn't the smallest, but is obviously correct otherwise, and really easy to compute: if you simply multiply 2 * 3 * 4 * 5 * 6 * ... N, you get a number that's clearly divisible by all of those smaller numbers.
Now, the question is how we can generate a smaller number with the same basic characteristic of being divisible by all the smaller number. We can do that by observing that (for example) 10 factors to 2 * 2 * 5, so (for example) we don't have to separately multiply by 2, 4 or 5 to get a result that's divisible by 2, 4 and 5.
So, we can take our list of numbers, and the prime factorization of each:
10: 2 * 2 * 5
9: 3 * 3
8: 2 * 2 * 2
7: 7
6: 2 * 3
5: 5
4: 2 * 2
3: 3
2: 2
1: 1
Then we can cross out factors later in the list that appear earlier in the list (but only up to as many times as they appear earlier in the list). That gives us something like this:
10: 2 * 2 * 5
9: 3 * 3
8: 2
7: 7
6: -
5: -
4: -
3: -
2: -
Multiply together what's left (2 * 2 * 5 * 3 * 3 * 2 * 7) and we get the 2520 we expect.
Applying the same technique to 20, we get a list like: 20 19 9 17 4 7 13 11. Multiplying that out, we get 232792560.
If you care more about efficiency, you can (for example) use Euclid's algorithm to compute the GCD of a pair of numbers. What we're computing here is the LCM of a pair of numbers, which is the product of the numbers divided by their GCD. We can then repeat using our previous LCM as one of the inputs to the GCD, so we end up with code something like this:
unsigned LCM = max;
for (int i = max - 1; i > 1; i--)
LCM = i * LCM / GCD(i, LCM);
There are quite a few ways to compute the GCD as well. A simple, well-known and fairly efficient one is Euclid's algorithm, which looks something like this:
unsigned GCD(unsigned u, unsigned v) {
while ( v != 0) {
unsigned r = u % v;
u = v;
v = r;
}
return u;
}
Using this, computing the LCM of 1..N for every N from 5 to 30 (and writing them to a file) takes about 3 ms on the machine I'm using at the moment (though I suspect more careful timing would prove it was really faster than that).

Computing the binomial coefficient in C

I found the following code for computing nCr, but don't understand the logic behind it. Why does this code work?
long long combi(int n,int k)
{
long long ans=1;
k=k>n-k?n-k:k;
int j=1;
for(;j<=k;j++,n--)
{
if(n%j==0)
{
ans*=n/j;
}else
if(ans%j==0)
{
ans=ans/j*n;
}else
{
ans=(ans*n)/j;
}
}
return ans;
}
that's a clever code!
In general it aims to calculate the following formula:
ans = n! / (k!)(n-k)!
It is equal to:
ans = n(n-1)(n-2) ... (n-k)...1 / k(k-1)...1 * (n-k)(n-k-1) ... 1
And after obvious cancellation:
ans = n(n-1)(n-2)..(n-k+1) / k!
Now notice that nominator and denominator have the same number of elements (k element)
So the calculation of ans will be like the following:
ans = 1 // initially
ans *= n/1
ans *= (n-1)/2
ans *= (n-2)/3
.
.
.
ans *= (n-k+1)/k
take a look again at the code and you notice that:
ans is being multiplied by n at each iteration
n is reduced by 1 at each iteration (n--)
ans is divided by j at each iteration
This is exactly what is done by the posted code, Now let's see the meanings of different conditions in the loop, with nominator starting from n and denominator from 1 to k, so variable j is assigned to denominator right?
1) if(n%j==0)
at each step if n/j is (computable) So we calculate it first here than multiply to the whole ans, this practice keeps the result at its smallest possible value.
2) else if(ans%j==0)
at each step if we couldn't calculate n/j but actually can calculate ans/j so that's not bad to say :
ans /= j; //first we divide
ans *= n; //then we multiply
This is always keeping our overall output as small as possible, right?
3) last condition
at each step, if we couldn't compute neither n/j nor ans/j in this case we are not lucky enough to divide first then multiply (hence keeping the result small). But well we need to carry on even-though we are left with only one choice which is
ans *= n; // multiply first
ans /= j; // then divide
ET VOILA!
Example
consider the case 3C7
we know that the answer is 7!/ 3!*4!
hence : ans = 7*6*5 / 1*2*3
let's see what happen at each iteration:
//1
ans = 1
//2
n = 7
j = 1
ans = ans * n/j
first compute 7/1 = 7
then multiply to ans
ans = 1*7
ans = 7
//3
n = 6
j = 2
ans = ans* n/j
evaluate n/j = 6/2 (can be divided)
n/j = 3
ans = ans *(n/j)
= 7 * 3
= 21
// 4
n = 5
j = 3
ans = ans * n/j
evaluate n/j = 5/3 oppsss!! (first if)
evaluate ans/j = 21/3 = 7 YES (second if)
ans = (ans/j)*n
= 7*5
= 35
// end iterations
Note that in last iteration if we calculate straight forward we would say:
ans = ans*n/j
= 21 * 5 / 3
= 105 / 3
= 34
yes it does find right result but meanwhile the value flies up to 105 before getting back to 35. Now imagine calculating real large numbers?!
Conclusion
This code is computing carefully the binomial coefficients trying to keep the output as small as possible at each step of calculation, it does that by checking if it is possible to divide (int) then execute, hence it is capable of calculating some very big kCn that the straightforward coding cannot handle (OverFlow may occur)
To answer the question in part, consider the fact that the entries of n choose k constitute Pascal's triangle. As Pascal's triangle is symmetric, it is sufficient to move the argument k into the left half, which is done with the
k=k>n-k?n-k:k;
statement; see the definition of C's conditional operator.
Furthermore, the result ans is initialized in the beginning to contain 1, which is the first entry of every row in Pascal's triangle, which means that initially, ans is in fact n choose j.
The fact is that nCr for 1<=k<=n/2 is same as in n/2+1<=k<=n.so first change in k so that it values lies value in the left half.One more thing nCk means (n*(n-1).....(n-k))/(k*(k-1)*....*2*1) so the above code apply it iteratively.
yes.
[N choose K] reduces its factorials a lot because the dividend and divisor share many factors that cancel each other out to x/x=1 (for x>0)
the trick is to not calculate the large factorials, because these large factors require too much address space (too many bits)
the first trick is to reduce the fraction, before dividing.
the second trick is to do modulo within a conditional to chose one of 3 operations for the current iteration. this can be done differently, and integer modulo is chosen to be a fast operator, skipping some slower integer division approaches.
you iteratively traverse pascals triangle.
with each path that you take, you multiply something.
There are 3 possible branching paths for every iterative step:
each of the 3 steps multiplies the accumulator "ans" with a different value, representing the factor between 2 "positions" on pascals triangle.
you always end up doing N multiplications, where N is the number of iterations, and end up at the binomial coefficient's value.
N is the column # of pascals triangle that you want to know, and you accumulate an N, multiplied by something, while reducing the number of column s (and lines) of pascals triangle by N=N-1 for each iteration.
j=1;
ans=0;
//within each iteration;
ans=ans*n;
n=n-1;
ans=ans/j;
j=n+1;
the integer division is slow and can be skipped (or made faster by making the divisor smaller) at least once, and often many more times (because there are a lot of shared prime factors in pascals triangle), this is being done by the modulo conditionals.
pascals triangle is extremely symmetric (on summing up its domains), therefore this works.
the difference between (partial) sums of columns of pascals triangle shows the symmetry that is important for the multiplications and divisions here.
just watch some youtube videos on the symmetries and identities of pascals triangle.

Project Euler Number 160 - attempt in C

Forgive me if I am being a bit silly, but I have only very recently started programming, and am maybe a little out of my depth doing Problem 160 on Project Euler. I have made some attempts at solving it but it seems that going through 1tn numbers will take too long on any personal computer, so I guess I should be looking into the mathematics to find some short-cuts.
Project Euler Problem 160:
For any N, let f(N) be the last five digits before the trailing zeroes
in N!. For example,
9! = 362880 so f(9)=36288 10! = 3628800 so f(10)=36288 20! =
2432902008176640000 so f(20)=17664
Find f(1,000,000,000,000)
New attempt:
#include <stdio.h>
main()
{
//I have used long long ints everywhere to avoid possible multiplication errors
long long f; //f is f(1,000,000,000,000)
f = 1;
for (long long i = 1; i <= 1000000000000; i = ++i){
long long p;
for (p = i; (p % 10) == 0; p = p / 10) //p is i without proceeding zeros
;
p = (p % 1000000); //p is last six nontrivial digits of i
for (f = f * p; (f % 10) == 0; f = f / 10)
;
f = (f % 1000000);
}
f = (f % 100000);
printf("f(1,000,000,000,000) = %d\n", f);
}
Old attempt:
#include <stdio.h>
main()
{
//This part of the programme removes the zeros in factorials by dividing by 10 for each factor of 5, and finds f(1,000,000,000,000) inductively
long long int f, m; //f is f(n), m is 10^k for each multiple of 5
short k; //Stores multiplicity of 5 for each multiple of 5
f = 1;
for (long long i = 1; i <= 100000000000; ++i){
if ((i % 5) == 0){
k = 1;
for ((m = i / 5); (m % 5) == 0; m = m / 5) //Computes multiplicity of 5 in factorisation of i
++k;
m = 1;
for (short j = 1; j <= k; ++j) //Computes 10^k
m = 10 * m;
f = (((f * i) / m) % 100000);
}
else f = ((f * i) % 100000);
}
printf("f(1,000,000,000,000) = %d\n", f);
}
The problem is:
For any N, let f(N) be the last five digits before the trailing zeroes in N!. Find f(1,000,000,000,000)
Let's rephrase the question:
For any N, let g(N) be the last five digits before the trailing zeroes in N. For any N, let f(N) be g(N!). Find f(1,000,000,000,000).
Now, before you write the code, prove this assertion mathematically:
For any N > 1, f(N) is equal to g(f(N-1) * g(N))
Note that I have not proved this myself; I might be making a mistake here. (UPDATE: It appears to be wrong! We'll have to give this more thought.) Prove it to your satisfaction. You might want to start by proving some intermediate results, like:
g(x * y) = g(g(x) * g(y))
And so on.
Once you have obtained a proof of this result, now you have a recurrence relation that you can use to find any f(N), and the numbers you have to deal with don't ever get much larger than N.
Prod(n->k)(k*a+c) mod a <=> c^k mod a
For example
prod[ 3, 1000003, 2000003,... , 999999000003 ] mod 1000000
equals
3^(1,000,000,000,000/1,000,000) mod 1000000
And number of trailing 0 in N! equals to number of 5 in factorisation of N!
I would compute the whole thing and then separate first nonzero digits from LSB ...
but for you I think is better this:
1.use bigger base
any number can be rewrite as sum of multiplies of powers of the same number (base)
like 1234560004587786542 can be rewrite to base b=1000 000 000 like this:
1*b^2 + 234560004*b^1 + 587786542*b^0
2.when you multiply then lower digit is dependent only on lowest digits of multiplied numbers
A*B = (a0*b^0+a1*b^1+...)*(b0*b^0+b1*b^1+...)
= (a0*b0*b^0)+ (...*b^1) + (...*b^2)+ ...
3.put it together
for (f=1,i=1;i<=N;i++)
{
j=i%base;
// here remove ending zeroes from j
f*=j;
// here remove ending zeroes from f
f%=base;
}
do not forget that variable f has to be big enough for base^2
and base has to be at least 2 digits bigger then 100000 to cover 5 digits and overflows to zero
base must be power of 10 to preserve decimal digits
[edit1] implementation
uint<2> f,i,j,n,base; // mine 64bit unsigned ints (i use 32bit compiler/app)
base="10000000000"; // base >= 100000^2 ... must be as string to avoid 32bit trunc
n="20"; // f(n) ... must be as string to avoid 32bit trunc
for (f=1,i=1;i<=n;i++)
{
j=i%base;
for (;(j)&&((j%10).iszero());j/=10);
f*=j;
for (;(f)&&((f%10).iszero());f/=10);
f%=base;
}
f%=100000;
int s=f.a[1]; // export low 32bit part of 64bit uint (s is the result)
It is too slow :(
f(1000000)=12544 [17769.414 ms]
f( 20)=17664 [ 0.122 ms]
f( 10)=36288 [ 0.045 ms]
for more speed or use any fast factorial implementation
[edit2] just few more 32bit n! factorials for testing
this statement is not valid :(
//You could attempt to exploit that
//f(n) = ( f(n%base) * (f(base)^floor(n/base)) )%base
//do not forget that this is true only if base fulfill the conditions above
luckily this one seems to be true :) but only if (a is much much bigger then b and a%base=0)
g((a+b)!)=g(g(a!)*g(b!))
// g mod base without last zeroes...
// this can speed up things a lot
f( 1)=00001
f( 10)=36288
f( 100)=16864
f( 1,000)=53472
f( 10,000)=79008
f( 100,000)=56096
f( 1,000,000)=12544
f( 10,000,000)=28125
f( 1,000,100)=42016
f( 1,000,100)=g(??????12544*??????16864)=g(??????42016)->42016
the more is a closer to b the less valid digits there are!!!
that is why f(1001000) will not work ...
I'm not an expert project Euler solver, but some general advice for all Euler problems.
1 - Start by solving the problem in the most obvious way first. This may lead to insights for later attempts
2 - Work the problem for a smaller range. Euler usually give an answer for the smaller range that you can use to check your algorithm
3 - Scale up the problem and work out how the problem will scale, time-wise, as the problem gets bigger
4 - If the solution is going to take longer than a few minutes, it's time to check the algorithm and come up with a better way
5 - Remember that Euler problems always have an answer and rely on a combination of clever programming and clever mathematics
6 - A problem that has been solved by many people cannot be wrong, it's you that's wrong!
I recently solved the phidigital number problem (Euler's site is down, can't look up the number, it's quite recent at time of posting) using exactly these steps. My initial brute-force algorithm was going to take 60 hours, I took a look at the patterns solving to 1,000,000 showed and got the insight to find a solution that took 1.25s.
It might be an idea to deal with numbers ending 2,4,5,6,8,0 separately. Numbers ending 1,3,7,9 can not contribute to a trailing zeros. Let
A(n) = 1 * 3 * 7 * 9 * 11 * 13 * 17 * 19 * ... * (n-1).
B(n) = 2 * 4 * 5 * 6 * 8 * 10 * 12 * 14 * 15 * 16 * 18 * 20 * ... * n.
The factorial of n is A(n)*B(n). We can find the last five digits of A(n) quite easily. First find A(100,000) MOD 100,000 we can make this easier by just doing multiplications mod 100,000. Note that A(200,000) MOD 100,000 is just A(100,000)*A(100,000) MOD 100,000 as 100,001 = 1 MOD 100,000 etc. So A(1,000,000,000,000) is just A(100,000)^10,000,000 MOD 100,000.
More care is needed with 2,4,5,6,8,0 you'll need to track when these add a trailing zero. Obviously whenever we multiply by numbers ending 2 or 5 we will end up with a zero. However there are cases when you can get two zeros 25*4 = 100.

how to calculate modulus division

I am stuck in a program while finding modulus of division.
Say for example I have:
((a*b*c)/(d*e)) % n
Now, I cannot simply calculate the expression and then modulo it to n as the multiplication and division are going in a loop and the value is large enough to not fit even in long long.
As clarified in comments, n can be considered prime.
I found that, for multiplication, I can easily calculate it as:
((a%n*b%n)%n*c%n)%n
but couldn't understand how to calculate the division part then.
The problem I am facing is say for a simple example:
((7*3*5)/(5*3)) % 11
The value of above expression would be 7
but if I calculate the multiplication, modulo, it would be like:
((7%11)*(3%11))%11 = 10
((10%11)*(5%11))%11 = 6
now I am left with 6/15 and I have no way to generate correct answer.
Could someone help me. Please make me understand the logic by above example.
Since 11 is prime, Z11 is a field. Since 15 % 11 is 4, 1/15 equals 3 (since 3 * 4 % 11 is 1). Therefore, 6/15 is 6 * 3 which is 7 mod 11.
In your comments below the question, you clarify that the modulus will always be a prime.
To efficiently generate a table of multiplicative inverses, you can raise 2 to successive powers to see which values it generates. Note that in a field Zp, where p is an odd prime, 2p-1 = 1. So, for Z11:
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 5
2^5 = 10
2^6 = 9
2^7 = 7
2^8 = 3
2^9 = 6
So the multiplicative inverse of 5 (which is 24) is 26 (which is 9).
So, you can generate the above table like this:
power_of_2[0] = 1;
for (int i = 1; i < n; ++i) {
power_of_2[i] = (2*power_of_2[i-1]) % n;
}
And the multiplicative inverse table can be computed like this:
mult_inverse[1] = 1;
for (int i = 1; i < n; ++i) {
mult_inverse[power_of_2[i]] = power_of_2[n-1-i];
}
In your example, since 15 = 4 mod 11, you actually end up with having to evaluate (6/4) mod 11.
In order to find an exact solution to this, rearrange it as 6 = ( (x * 4) mod 11), which makes clearer how the modulo division works.
If nothing else, if the modulus is always small, you can iterate from 0 to modulus-1 to get the solution.
Note that when the modulus is not prime, there may be multiple solutions to the reduced problem. For instance, there are two solutions to 4 = ( ( x * 2) mod 8): 2 and 6. This will happen for a reduced problem of form:
a = ( (x * b) mod c)
whenever b and c are NOT relatively prime (ie whenever they DO share a common divisor).
Similarly, when b and c are NOT relatively prime, there may be no solution to the reduced problem. For instance, 3 = ( (x * 2) mod 8) has no solution. This happens whenever the largest common divisor of b and c does not also divide a.
These latter two circumstances are consequences of the integers from 0 to n-1 not forming a group under multiplication (or equivalently, a field under + and *) when n is not prime, but rather forming simply the less useful structure of a ring.
I think the way the question is asked, it should be assumed that the numerator is divisible by the denominator. In that case the finite field solution for prime n and speculations about possible extensions and caveats for non-prime n is basically overkill. If you have all the numerator terms and denominator terms stored in arrays, you can iteratively test pairs of (numerator term, denominator term) and quickly find the greatest common divisor (gcd), and then divide the numerator term and denominator term by the gcd. (Finding the gcd is a classical problem and you can easily find a simple solution online.) In the worst case you will have to iterate over all possible pairs but at some point, if the denominator indeed divides the numerator, then you'll eventually be left with reduced numerator terms and all denominator terms will be 1. Then you're ready to apply multiplication (avoiding overflow) the way you described.
As n is prime, dividing an integer b is simply multiplying b's inverse. That is:
(a / b) mod n = (a * inv(b)) mod n
where
inv(b) = (b ^ (n - 2)) mod n
Calculating inv(b) can be done in O(log(n)) time using the Exponentiation by squaring algorithm. Here is the code:
int inv(int b, int n)
{
int r = 1, m = n - 2;
while (m)
{
if (m & 1) r = (long long)r * b % n;
b = (long long)b * b % n;
m >>= 1;
}
return r;
}
Why it works? According to Fermat's little theorem, if n is prime, b ^ (n - 1) mod n = 1 for any positive integer b. Therefore we have inv(b) * b mod n = 1.
Another solution for finding inv(b) is the Extended Euclidean algorithm, which needs a bit more code to implement.
I think you can distribute the division like
z = d*e/3
(a/z)*(b/z)*(c/z) % n
Remains only the integer division problem.
I think the problem you had was that you picked a problem that was too simple for an example. In that case the answer was 7 , but what if a*b*c was not evenly divisible by c*d ? You should probably look up how to do division with modulo first, it should be clear to you :)
Instead of dividing, think in terms of multiplicative inverses. For each number in a mod-n system, there ought to be an inverse, if certain conditions are met. For d and e, find those inverses, and then it's all just multiplying. Finding the inverses is not done by dividing! There's plenty of info out there...

Resources