I was trying to solve http://poj.org/problem?id=1426 (2002 dhaka regional) . Though I was not able to come up with the exact algorithm required but as n varied from 1 to 200 I precomputed all the values by generating binary numbers and checking for divisibility. Now I have a constant time algorithm :) but I am sure this is not the correct approach for the problem. I don't want use graph search algos as this problem was under basic math in a site so I think there must be a mathematical solution to this problem which does not give TLE.
It's a simple trick on the remainder.
Having to write every multiple with only 0 and 1, means that you want a multiple that is sum of some powers of 10, that means x=\sum{10^a(i)} for some {a(i)}. To find the proper index we want to keep, you must remember that, being a multiple of a number n means that x mon n = 0.
So, it's all about writing the powers of 10 mod n, and find a subset which sum is 0 mod n.
Let's try with 19:
Num -> Num mod 19
1 -> 1
10 -> 10
10^2 -> 5
10^3 -> 12
10^4 -> 6
10^5 -> 3
now, we can see that 10^1 + 10^4 + 10^5 = 19 that is 0 mod 19, so our solution is 110010 .
To find the reminder mod 19 you don't have to calculate every single power, you just can multiply the previous value mod 19 per 10, and then calculate the module.
For instance, 10^4 mod 10 = 10^3 * 10 mod 19 = 12*10 mod 19 = 6 , that is way easier than calculate 10^4 (maybe it's not for small powers, but imagine having to calculato 100^100 before making it mod 19).
EDIT
The only problem left is find a subset that sums to 0 mod n, assuming such a subset exist.
EDIT
Ok, I have got the idea that works up to n = 200 and solve the problem on linear time. Basically, you exploit the fact that sums mod n sooner or later will overlap. This is true because of hte pigeot principle, BUT in the specific case, having only 100 integers, having it working is just a mere case. Anyway, given the list of reminders calculated as shown before, you start calculatin the partial sums. If you meet a value that you already had, you have the solution (i-1 1's followed by j 0). If you meet a reminder 0, you are as well done.
Here is the C# code I've written to test it:
for (int n = 2; n <= 200; n++)
{
int[] reminder = new int[100];
reminder[0] = 1;
for (int i = 1; i < 100; i++)
{
reminder[i] = (10 * reminder[i - 1]) % n;
}
var lst = reminder.Select((x, y) => new TenPower { Reminder = x, Pow = y })
.ToList();
bool cont = true;
for (int i = 1; (i < 100)&&cont; i++)
{
if (lst[i].Reminder == 0)
{
cont = false;
Console.WriteLine(n +" :: " + Math.Pow(10, lst[i].Pow));
}
else
{
lst[i].Reminder = (lst[i].Reminder + lst[i - 1].Reminder) % n;
if (lst[i].Reminder == 0)
{
cont = false;
Console.WriteLine(n + " :: " + Math.Pow(10, lst[i].Pow));
}
for (int j = i - 1; (j > 0) && cont; j--)
{
if (lst[i].Reminder == lst[j].Reminder)
{
cont = false;
Console.Write(n + " :: ");
for (int k = 0; k < i - j; k++)
{
Console.Write("1");
}
for (int k = i - j-1; k < i; k++)
{
Console.Write("0");
}
Console.WriteLine();
}
}
}
}
}
Related
Maximum Product.
The input to the problem is a string Z = z1,z2.....zn where each zi is any number between 1...9 and an integer k where 0 <= k < n.
An example string is Z = 8473817, which is of length n = 7. We want to insert k multiplication operators X into the string so that the mathematical result of the expression
is the largest possible. There are n - 1 possible locations for the operators,
namely, after the ith character where i = 1,....., n - 1.
For example, for input Z = 21322 and k = 2, then one possible way to insert the X operators
is: 2 X 1 X 322 = 644, another possibility is 21 X 3 X 22 = 1386.
Design a dynamic programming to output the maximum product
obtainable from inserting exactly k multiplication operators X into the string.
You can assume that all the multiplication operations in your algorithm take
O(1) time.
I am approaching this using the Matrix Chain Multiplication method where you compute smaller subproblem along the upper diagonal.
This works when K=1 i.e. one multiplication operator is inserted.
In the picture below, I have used 8473817 as an example and shown that 8473 X 817 yields the highest product.
How do I scale this solution for K > 1 and K < N.
Update: adding a pseudo code.
let A(i,j) store the max product for the strings A(i...j) 1 < i < j < n
for i = 1 -> n:
A(i,i) = Z(i)
for s = 1 -> n-1:
for i = 1 -> n-s:
j = i + s
A(i,j) = 0
for l = i -> j-1:
A(i,j) = max (A(i,j), A(i,l) * A(l+1,j)
return A(1,n)
The above code works when k = 1. How do I scale this up when k > 1 and less than n
Update
Based on #trincot solution, I revamped the soln to not use memoization
Sub problem Defn
Let T(i) store the start offset where inserting the X operator in Z yields max value for i : 1 < i < k.
Pseudo code
`
T(0) = 0
for i = 1 -> k:
max = 0
for j = T(i-1) + 1 -> n:
result = Z[1..j] * Z[j+1..n]
if result > max
max = result
T(i) = j
val = 1
for i = 1 -> k:
val = val * Z[T(i-1)+1...T(i)]
val = val * Z[T(k)+1..n]
Your pseudo code is a dynamic programming solution where you use memoization for every possible slice of z (2 dimensions, starting and ending offset). However, you would only need to memoize the best result for any suffix of z, so you would only need one (starting) offset. A second dimension in your memoization would then be used for the value of k (the number of remaining multiplications).
So you would still need a 2-dimensional table for memoization, but one index would be for k and the other for an offset in z.
Here is an implementation in JavaScript:
function solve(z, k) {
// Initialise a kxl array (where l is the length of z), filled with zeroes.
const memo = Array.from({length: k + 1}, () => Array(z.length + 1).fill(0));
function recur(z, k) {
if (k == 0) return z;
let result = memo[k][z.length];
if (result == 0) {
for (let i = 1; i <= z.length - k; i++) {
result = Math.max(result, +z.slice(0, i) * recur(z.slice(i), k - 1));
}
memo[k][z.length] = result;
}
return result;
}
return recur(z, k);
}
// A few example runs:
console.log(solve('8473817', 1)); // 6922441
console.log(solve('21322', 2)); // 1368
console.log(solve('191111', 2)); // 10101
Bottom up
The same can be done in an iterative algorithm -- bottom-up instead of top-down. Here we can save one dimension of the memoization array, as the same array can be re-used for the next value of k as it increases from 0 to its final value:
function solve(z, k) {
const memo = Array(z.length);
// Initialise for k=0:
// the best product in a suffix is the suffix itself
for (let i = 0; i < z.length; i++) {
memo[i] = +z.slice(i);
}
for (let kk = 1; kk <= k; kk++) {
for (let i = 0; i < z.length - kk; i++) {
// find best position for multiplication
let result = 0;
for (let j = i + 1; j < z.length - kk + 1; j++) {
result = Math.max(result, +z.slice(i, j) * memo[j]);
}
memo[i] = result;
}
}
return memo[0];
}
// A few example runs:
console.log(solve('8473817', 1)); // 6922441
console.log(solve('21322', 2)); // 1368
console.log(solve('191111', 2)); // 10101
(Code not supplied because this is homework.)
You have found that you can use the method once and get a solution for k=1.
Can you do it and find the best solution ending at every position in the string?
Now can you use the output of that second generalization and a similar method to get a complete solution for k=2?
Now can you write this a loop to solve for arbitrary k?
If you can do all that, then finishing is easy.
You have n-1 positions and k operators to insert. To me that looks like a binary number with n-1 bits including k 1's and the other positions set to 0.
Systematically generate all permutations of [0..01..1], insert multiplication operators at the 1 positions and calculate the result for each permutation.
Recently, In a competitive coding exam I got this question -
A good number is number whose sum of digits is divisible by 5. example - 5 (5), 14 (1+4), 19(1+9), 23(2+3)
Question is - you are provided a integer n and another integer k you have to find kth good number greater the n.
Constraints - 1<k<10^9
Sample test 1 -
input: n = 6, k = 5
output: 32
Explanation: After 6 good numbers are - 14, 19, 23, 28, 32 (5th is 32)
Sample test 2 -
input: n = 5, k = 1
output: 14
Explanation: 5 is 1st good number but we need greater than 5 so ans is 14
I have tried it with native approach i.e for each number greater then n checking if it is good and loop until I found k good numbers, here is my code -
def solve(n,k):
n+=1
count = 0
while count<k:
if sum(map(int,str(n)))%5==0:
count+=1
n+=1
return n-1
but above code was gave me TLE, how to do it in better time complexity, I have searched on internet for similar question but unable to find, help.
Let's start with a simple question:
I give you a list of five consecutive numbers. How many of those numbers are divisible by 5? (I'm not talking abouts sums of digits yet. Just the numbers, like 18, 19, 20, 21, 22.
No problem there, right? So a slightly different question:
In a list of ten consecutive numbers, how many are divisible by 5?
Still pretty easy, no? Now let's look at your "good" numbers. We'll start by introducing the function digit_sum(n), which is the sum of the digits in n. For now, we don't need to write that function; we just need to know it exists. And here's another simple question:
If n is a number which does not end in the digit 9 and s is digit_sum(n), what is digit_sum(n+1)? (Try a few numbers if that's not immediately clear.) (Bonus question: why does it matter whether the last digit is 9? Or to put it another way, why doesn't it matter which digit other than 9 is at the end? What's special about 9?)
Ok, almost there. Let's put these two ideas together:
Suppose n ends with 0. How many of the ten numbers digit_sum(n), digit_sum(n+1), digit_sum(n+2), … digit_sum(n+9) are divisible by 5? (See question 2).
Does that help you find a quick way to compute the kth good number after n? Hopefully, the answer is yes. Now you just need to generalise a little bit.
maybe your digits algorithm is too time consuming? try this:
def digits(n):
sum = 0
while n:
n, r = divmod(n, 10)
sum += r
return sum
def solve(n,k):
n+=1
count = 0
while count<k:
if digits(n)%5==0:
count+=1
n+=1
return n-1
still it’s a trivial solution, and always you can run it offline and just submit a lookups table.
And here is a link for this sequence: http://oeis.org/A227793
Here's a digit dynamic-program that can answer how many such numbers we can find from 1 to the parameter, k. The function uses O(num_digits) search space. We could use it to search for the kth good number with binary search.
The idea generally is that the number of good numbers that include digit d in the ith position, and have a prefix mod 5 of mod1 so far, is equal to the count of valid digit-suffixes that have the complementary mod, mod2, so that (mod1 + mod2) mod 5 = 0.
JavaScript code comparing with brute force:
function getDigits(k){
const result = [];
while (k){
result.push(k % 10);
k = ~~(k / 10);
}
return result.reverse();
}
function g(i, mod, isK, ds, memo){
const key = String([i, mod, isK]);
if (memo.hasOwnProperty(key))
return memo[key];
let result = 0;
const max = isK ? ds[i] : 9;
// Single digit
if (i == ds.length-1){
for (let j=0; j<=max; j++)
result += (j % 5 == mod);
return memo[key] = result;
}
// Otherwise
for (let j=0; j<=max; j++){
const m = j % 5;
const t = (5 + mod - m) % 5;
const next = g(i+1, t, isK && j == max, ds, memo);
result += next;
}
return memo[key] = result;
}
function f(k){
if (k < 10)
return (k > 4) & 1;
const ds = getDigits(k);
const memo = {};
let result = -1;
for (let i=0; i<=ds[0]; i++){
const m = i % 5;
const t = (5 - m) % 5;
const next = g(1, t, i==ds[0], ds, memo);
result += next;
}
return result;
}
function bruteForce(k){
let result = 0;
//let ns = [];
for (let i=1; i<=k; i++){
const ds = getDigits(i);
const sum = ds.reduce((a, b) => a + b, 0);
if (!(sum % 5)){
//ns.push(i);
result += 1;
}
}
//console.log(ns);
return result;
}
var k = 3000;
for (let i=1; i<k; i++){
const _bruteForce = bruteForce(i);
const _f = f(i);
if (_bruteForce != _f){
console.log(i);
console.log(_bruteForce);
console.log(_f);
break;
}
}
console.log('Done.');
Hi guys I'm practicing dynamic programming and came across the following problem:
Given a number K, 0 <= K <= 10^100, a sequence of digits N, what is the number of possible ways of dividing N so that each part is at most K?
Input:
K = 8
N = 123
Output: 1
Explanation:
123
1-23
12-3
1-2-3
Are all possibilities of spliting N and only the last one is valid...
What I have achieved so far:
Let Dp[i] = the number of valid ways of dividing N, using i first digits.
Given a state, i must use the previous answer to compute new answers, we have 2 possibilities:
Use dp[i-1] + number of valid ways that split the digit i
Use dp[i-1] + number of valid ways that not split the digit i
But I'm stuck there and I don't know what to do
Thanks
Using dynamic programming implies that you need to think about the problem in terms of subproblems.
Let's denote by N[i...] the suffix of N starting at index i (for instance, with N = 45678955, we have N[3...] = 78955)
Let's denote by dp[i] the number of possible ways of dividing N[i...] so that each part is at most K.
We will also use a small function, max_part_len(N, K, i) which will represent the maximum length of a 'part' starting at i. For instance, with N = 45678955, K = 37, i = 3, we have max_part_len(N, K, i) = 1 because 7 < 37 but 78 > 37.
Now we can write the recurrence (or induction) relation on dp[i].
dp[i] = sum_(j from 1 to max_part_len(N, K, i)) dp[i+j]
This relation means that the the number of possible ways of dividing N[i...] so that each part is at most K, is:
The sum of the the number of possible ways of dividing N[i+j...] so that each part is at most K, for each j such that N[i...j] <= k.
From there the algorithm is quite straight forward if you understood the basics of dynamic programming, I leave this part to you ;-)
I think we can also use divide and conquer. Let f(l, r) represent the number of ways to divide the range of digits indexed from l to r, so that each part is at most k. Then divide the string, 45678955 in two:
4567 8955
and the result would be
f(4567) * f(8955)
plus a division with a part that includes at least one from each side of the split, so each left extension paired with all right extensions. Say k was 1000. Then
f(456) * 1 * f(955) + // 78
f(456) * 1 * f(55) + // 789
f(45) * 1 * f(955) // 678
where each one of the calls to f performs a similar divide and conquer.
Here's JavaScript code comparing a recursive (top-down) implementation of m.raynal's algorithm with this divide and conquer:
function max_part_len(N, K, i){
let d = 0;
let a = 0;
while (a <= K && d <= N.length - i){
d = d + 1;
a = Number(N.substr(i, d));
}
return d - 1;
}
// m.raynal's algorithm
function f(N, K, i, memo={}){
let key = String([N, i])
if (memo.hasOwnProperty(key))
return memo[key];
if (i == N.length)
return 1
if (i == N.length - 1)
return (Number(N[i]) <= K) & 1
let s = 0;
for (let j=1; j<=max_part_len(N, K, i); j++)
s = s + f(N, K, i + j, memo);
return memo[key] = s;
}
// divide and conquer
function g(N, K, memo={}){
if (memo.hasOwnProperty(N))
return memo[N];
if (!N)
return memo[N] = 1;
if (N.length == 1)
return memo[N] = (Number(N) <= K) & 1;
let mid = Math.floor(N.length / 2);
let left = g(N.substr(0, mid), K);
let right = g(N.substr(mid), K);
let s = 0;
let i = mid - 1;
let j = mid;
let str = N.substring(i, j + 1);
while (i >= 0 && Number(str) <= K){
if (j == N.length){
if (i == 0){
break;
} else{
i = i - 1;
j = mid;
str = N.substring(i, j + 1);
continue
}
}
let l = g(N.substring(0, i), K, memo);
let r = g(N.substring(j + 1, N.length, memo), K);
s = s + l * r;
j = j + 1;
str = N.substring(i, j + 1);
if (Number(str) > K){
j = mid;
i = i - 1;
str = N.substring(i, j + 1);
}
}
return memo[N] = left * right + s;
}
let start = new Date;
for (let i=5; i<100000; i++){
let k = Math.ceil(Math.random() * i)
let ii = String(i);
let ff = f(ii, k, 0);
}
console.log(`Running f() 100,000 times took ${ (new Date - start)/1000 } sec`)
start = new Date;
for (let i=5; i<100000; i++){
let k = Math.ceil(Math.random() * i)
let ii = String(i);
let gg = g(ii, k);
}
console.log(`Running g() 100,000 times took ${ (new Date - start)/1000 } sec`)
start = new Date;
for (let i=5; i<100000; i++){
let k = Math.ceil(Math.random() * i)
let ii = String(i);
let ff = f(ii, k, 0);
let gg = g(ii, k);
if (ff != gg){
console.log("Mismatch found.", ii, k, ff, gg);
break;
}
}
console.log(`No discrepancies found between f() and g(). ${ (new Date - start)/1000 } sec`)
In other words, given a set of n positive integers A and a threshold B, I want to find the smallest C so that:
C > B
C = A[1] * k[1] + A[2] * k[2] + ... + A[n] * k[n], k[i] are integers >= 0
As an example if A = { 6, 11, 16 } then the values we can obtain are: { 0, 6, 11, 12, 16, 17, 18, 22, 23, 24, 27, 28, 29, 30, 32 ... } so if B = 14 then C would be 16, B = 22 => C = 23, B = 18 => C = 22
This problem was given these constraints: 2 < n < 5000 0 < A[i] < 50000 and 1 < B < 10^9 ( this is why I got stuck ). Also you had to calculate for an array B of size < 1000 an array C (but this may not matter). And the algorithm should run in under 0.3 sec in C++.
An algorithm like the one described here solves it but it is not fast enough: https://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/
I calculate table until B + Amin because Amin * k <= B <= Amin * ( k + 1 ) <= B + Amin
Here's the algorithm (in pseudo C++):
int n, A[n], B;
int Amin; // smallest number from A
// table[i] will tell us if it is possible or not to obtain the number i
bool table[B + Amin];
table[0] = true;
for( int i = 0; i < n; ++i )
{
int x = A[i]; // current number / denomination
for( int j = x; j <= B + Amin; ++j )
if( table[j - x] )
table[j] = true;
}
// now we can do something like this:
int result = B + 1;
while( !table[result] )
++result;
This algorithm has a complexity of O(n*B) and I'm looking for something that is independent of B ( or maybe has O(log(B)) or O(sqrt(B)) )
Note: if we make the first requirement C >= B then the problem doesn't change ( just add +1 to B ) and we can ask it like this: If we have specific coins or banknotes ( infinite of them ) and want to purchase something with them, then what is the amount we can pay so that the cashier has to give back minimal change.
Things that I suspect may help:
https://en.wikipedia.org/wiki/Coin_problem
If Greatest Common Divisor ( x, y ) = 1 then anything higher than xy − x − y can be obtained using x and y.
https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
https://en.wikipedia.org/wiki/Subset_sum_problem
Edit: added example and note.
I don't think you can get better than O(n*B), because the Frobenius number (above this number all amounts can be built with the given denominations) of 49999 and 49998 is 2499750005 a lot bigger than 10^9 and you need to calculate the best value at least for some inputs. If gcd(A) > 1 then the Frobenius number doesn't exist, but this could be prevented by dividing all A and B (round down) by gcd(A) and multiply the C you get by gcd(A) to get the final result.
There is still a lot of room for improvements in your pseudo code. You look at all denominations almost B+Amin times and also set the value in the table to true multiple times.
The standard implementation would look something like this:
sort(A);
table[0] = true;
for (int i = A[0]; i <= B + A[0]; i++)
for (int j = 0; j < n && A[j] <= i; j++)
if (table[i - A[j]]) {
table[i] = true;
break;
}
This is already a little better (note the break). I call it the backwards implementation, because you look back from all positions in the table to see if you can find a value which has the difference of one of the given denominations. You could also introduce a counter for the number of consecutive values set to true in the table (increase the counter when you set a value in the table to true, reset if the value couldn't be built, return B+1 if counter == A[0] - 1).
Maybe you could even get better results with a forward implementation, because the table can be very sparse, here table values which are false are skipped instead of denominations:
table[0] = true;
for (int i = 0; i <= B + Amin; i++)
if (table[i])
for (j = 0; j < n; j++)
if (i + A[j] <= B + Amin)
table[i + A[j]] = true;
I am given N numbers i want to calculate sum of a factorial modulus m
For Example
4 100
12 18 2 11
Ans = (12! + 18! +2!+11!)%100
Since the 1<N<10^5 and Numbers are from 1<Ni<10^17
How to calculate it in efficient time.
Since the recursive approach will fail i.e
int fact(int n){
if(n==1) return 1;
return n*fact(n-1)%m;
}
if you precalculate factorials, using every operation %m, and will use hints from comments about factorials for numbers bigger than m you will get something like this
fact = new int[m];
f = fact[0] = 1;
for(int i = 1; i < m; i++)
{
f = (f * i) % m;
fact[i] = f;
}
sum = 0
for each (n in numbers)
{
if (n < m)
{
sum = (sum + fact[n]) % m
}
}
I'm not sure if it's best but it should work in a reasonable amount of time.
Upd: Code can be optimized using knowledge that if for some number j, (j!)%m ==0 than for every n > j (n!)%m ==0 , so in some cases (usually when m is not a prime number) it's not necessary to precalculate factorials for all numbers less than m
try this:
var numbers = [12,18,2,11]
function fact(n) {
if(n==1) return 1;
return n * fact(n-1);
}
var accumulator = 0
$.each(numbers, function(index, value) {
accumulator += fact(value)
})
var answer = accumulator%100
alert(accumulator)
alert(answer)
you can see it running here:
http://jsfiddle.net/orw4gztf/1/