Calculating the modulus of a large number - discrete-mathematics

I am studying for a quiz in discrete structures. How can I calculate 2^50 (mod5)? I can calculate the result with smaller numbers with the use of a calculator but I can not do it with a large number.

Let's say we have a number N = 5X + Y, where N, X and Y are whole numbers (i.e. N mod 5 = Y). It would follow then that since 2N = 2(5X + Y) = 10x + 2Y, that 2N mod 5 = 2Y mod 5.
Similarily, since 2^50 can be rewritten as ((2^5)^5)^2:
2^50 mod 5 = ((2^5 mod 5)^5 mod 5)^2 mod 5
2^50 mod 5 = ((2)^5 mod 5)^2 mod 5
2^50 mod 5 = (2)^2 mod 5
2^50 mod 5 = 4

You can make use of the fact that if (2^x = t)(mod A) then (2^(x*y) = t^y)(mod A).
Hence, we have:
2^2 = (-1) (mod 5) which means
2^50 = (-1)^25(mod 5)
= -1 (mod 5) (which is the same as 4 (mod 5))
Using actual computation, we see 2^50 = 1125899906842624 = -1(mod 5).

Related

Multiply matrix columns with decreasing elements starting by the last column

I have a matrix with following shape:
A = [1 2 3;
4 5 6;
7 8 9]
Now I want starting with the last column to multiply the column with a number and then decrease the number and move to the next column.
So if we start with the number 1 and use for step 0.2 to modify all columns:
Anew = [1*0.6 2*0.8 3*1;
4*0.6 5*0.8 6*1;
7*0.6 8*0.8 9*1]
Or for second example we start with 0.9 with 0.1 as step and modify 3 columns:
B = [1 2 3 4;
5 6 7 8;
9 10 11 12;
13 14 15 16]
And to get:
Bnew = [1 2*0.7 3*0.8 4*0.9;
5 6*0.7 7*0.8 8*0.9;
9 10*0.7 11*0.8 12*0.9;
13 14*0.7 15*0.8 16*0.9]
The matrices might vary in their amount of columns, and I would like to set starting number, ending number, step number and the amount of columns I want to modify.
What you are describing can be achieved with broadcasted element-wise multiplication in matlab R2016b and beyond.
Let's say your inputs are the matrix A, start value start, step size step, and number n. You can start by constructing the factors you want to multiply by. I am going to assume that when n > size(A, 2), you want to just use the first n steps rather than error out:
k = size(A, 2);
n = min(n, k);
factors = ones(1, k);
factors(1 + k - n:end) = linspace(start - (n - 1) * step, start, n);
Now you can just multiply your matrix:
result = A .* factors;
This solution has the advantage of being extremely simple and fully vectorized.
If you have an older version of MATLAB, do the following instead:
result = A .* repmat(factors, size(A, 1), 1);
Or use Tony's trick:
result = A .* factors(ones(3, 1), :)
I just found the solution:
count = 0;
A = randi([-10,10],4,4);
Anew = [];
for i=0.9:-0.1:0
number_columns = 3;
if count == number_columns
rest = existing_columns - count;
for i=rest:-1:1
Anew = [(A(:,i)) Anew];
end
break
end
existing_columns = size(A,1);
Anew = [(A(:,existing_columns-count)*i) Anew];
count = count + 1;
end

Generate cell with random pairs without repetitions

How to generate a sequence of random pairs without repeating pairs?
The following code already generates the pairs, but does not avoid repetitions:
for k=1:8
Comb=[randi([-15,15]) ; randi([-15,15])];
T{1,k}=Comb;
end
When running I got:
T= [-3;10] [5;2] [1;-5] [10;9] [-4;-9] [-5;-9] [3;1] [-3;10]
The pair [-3,10] is repeated, which cannot happen.
PS : The entries can be positive or negative.
Is there any built in function for this? Any sugestion to solve this?
If you have the Statistics Toolbox, you can use randsample to sample 8 numbers from 1 to 31^2 (where 31 is the population size), without replacement, and then "unpack" each obtained number into the two components of a pair:
s = -15:15; % population
M = 8; % desired number of samples
N = numel(s); % population size
y = randsample(N^2, M); % sample without replacement
result = s([ceil(y/N) mod(y-1, N)+1]); % unpack pair and index into population
Example run:
result =
14 1
-5 7
13 -8
15 4
-6 -7
-6 15
2 3
9 6
You can use ind2sub:
n = 15;
m = 8;
[x y]=ind2sub([n n],randperm(n*n,m));
Two possibilities:
1.
M = nchoosek(1:15, 2);
T = datasample(M, 8, 'replace', false);
2.
T = zeros(8,2);
k = 1;
while (k <= 8)
t = randi(15, [1,2]);
b1 = (T(:,1) == t(1));
b2 = (T(:,2) == t(2));
if ~any(b1 & b2)
T(k,:) = t;
k = k + 1;
end
end
The first method is probably faster but takes up more memory and may not be practicable for very large numbers (ex: if instead of 15, the max was 50000), in which case you have to go with 2.

Convert for loop into vector expression

I'm new to MATLAB and learning to use vector expressions instead of verbose for loops. I have a snippet and I was wondering whether it could even be written in a concise vector and if so how would I modify it.
for v = I
X(i, v) = X(i, v) + length(I(I == v));
end
X is 1500x200
I is 3763x1
i can be thought of as a constant
What I'm doing here is this. I contains column indexes of X and I want to increment those locations by the number of times that particular index appeared in I. So after this for loop is done the ith row of X will contain a histogram.
Any other ideas or suggestions to improve my MATLAB coding would also be appreciated.
Here's a couple of ways:
I = randi(10, [50,1]);
X = zeros (1, 10);
for Col = 1 : size (X, 2)
X(1, Col) = sum (I == Col);
end
% X = 7 7 3 3 7 4 5 8 1 5
X = zeros (1, 10);
for Col = I.' % the transpose operation is needed to convert to horizontal!
X(1, Col) += 1;
end
% X = 7 7 3 3 7 4 5 8 1 5
X = zeros (1, 10);
X = accumarray (I, ones (size (I)), size (X))
% X = 7 7 3 3 7 4 5 8 1 5

ind2sub for nonzero elements of triangular matrix

I just wanted to simply find the index of (row, col) that is a minimum point of a matrix A. I can use
[minval, imin] = min( A(:) )
and MATLAB built in function
[irow, icol] = ind2sub(imin);
But for efficiency reason, where matrix A is trigonal, i wanted to implement the following function
function [i1, i2] = myind2ind(ii, N);
k = 1;
for i = 1:N
for j = i+1:N
I(k, 1) = i; I(k, 2) = j;
k = k + 1;
end
end
i1 = I(ii, 1);
i2 = I(ii, 2);
this function returns 8 and 31 for the following input
[irow, icol] = myind2ind(212, 31); % irow=8, icol = 31
How can I implement myind2ind function more efficient way without using the internal "I"?
The I matrix can be generated by nchoosek.
For example if N = 5 we have:
N =5
I= nchoosek(1:N,2)
ans =
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
so that
4 repeated 1 times
3 repeated 2 times
2 repeated 3 times
1 repeated 4 times
We can get the number of rows of I with the Gauss formula for triangular number
(N-1) * (N-1+1) /2 =
N * (N -1) / 2 =
10
Given jj = size(I,1) + 1 - ii as a row index I that begins from the end of I and using N * (N -1) / 2 we can formulate a quadratic equation:
N * (N -1) / 2 = jj
(N^2 -N)/2 =jj
So
N^2 -N - 2*jj = 0
Its root is:
r = (1+sqrt(8*jj))/2
r can be rounded and subtracted from N to get the first element (row number of triangular matrix) of the desired output.
R = N + 1 -floor(r);
For the column number we find the index of the first element idx_first of the current row R:
idx_first=(floor(r+1) .* floor(r)) /2;
The column number can be found by subtracting current linear index from the linear index of the first element of the current row and adding R to it.
Here is the implemented function:
function [R , C] = myind2ind(ii, N)
jj = N * (N - 1) / 2 + 1 - ii;
r = (1 + sqrt(8 * jj)) / 2;
R = N -floor(r);
idx_first = (floor(r + 1) .* floor(r)) / 2;
C = idx_first-jj + R + 1;
end

matlab - find index for when values exceeds a threshold n number of times

I would like to find the index for when an array exceeds a certain value, and this value is value is exceeded for a duration, n. For examples:
n = 5;
dat = [1,2,2,1.5,2,4,2,1,1,3,4,6,8,4,9];
Here, I would like to find when 'dat' exceeds 2 for a duration greater than n for the first time. So, the solution here should lead to an answer:
ans = 10
Another example:
n = 7;
dat = [1,1,2,3,4,5,6,7,8,9,9,6,4,3,2,4,6,7,7,5];
find the first time that 'dat' exceeds or equals 5 for more than or equal to n times.
ans = 6
n = 5;
m = 2;
dat = [1,2,2,1.5,2,4,2,1,1,3,4,6,8,4,9];
c = conv(double(dat >= m), ones(1, n))
%I think you can also do
% c = conv((dat >= m)*1, ones(1, n))
min(find(c == n)) - n + 1
n=5
x=2;
dat = [1,2,2,1.5,2,4,2,1,1,3,4,6,8,4,9];
vec= cumsum(dat>=x);
ind=find(vec>=n);
ind=dat(ind(1));
ind will contain the answer 10