How to find multiplicative partitions of any integer? - algorithm

I'm looking for an efficient algorithm for computing the multiplicative partitions for any given integer. For example, the number of such partitions for 12 is 4, which are
12 = 12 x 1 = 4 x 3 = 2 x 2 x 3 = 2 x 6
I've read the wikipedia article for this, but that doesn't really give me an algorithm for generating the partitions (it only talks about the number of such partitions, and to be honest, even that is not very clear to me!).
The problem I'm looking at requires me to compute multiplicative partitions for very large numbers (> 1 billion), so I was trying to come up with a dynamic programming approach for it (so that finding all possible partitions for a smaller number can be re-used when that smaller number is itself a factor of a bigger number), but so far, I don't know where to begin!
Any ideas/hints would be appreciated - this is not a homework problem, merely something I'm trying to solve because it seems so interesting!

The first thing I would do is get the prime factorization of the number.
From there, I can make a permutation of each subset of the factors, multiplied by the remaining factors at that iteration.
So if you take a number like 24, you get
2 * 2 * 2 * 3 // prime factorization
a b c d
// round 1
2 * (2 * 2 * 3) a * bcd
2 * (2 * 2 * 3) b * acd (removed for being dup)
2 * (2 * 2 * 3) c * abd (removed for being dup)
3 * (2 * 2 * 2) d * abc
Repeat for all "rounds" (round being the number of factors in the first number of the multiplication), removing duplicates as they come up.
So you end up with something like
// assume we have the prime factorization
// and a partition set to add to
for(int i = 1; i < factors.size; i++) {
for(List<int> subset : factors.permutate(2)) {
List<int> otherSubset = factors.copy().remove(subset);
int subsetTotal = 1;
for(int p : subset) subsetTotal *= p;
int otherSubsetTotal = 1;
for(int p : otherSubset) otherSubsetTotal *= p;
// assume your partition excludes if it's a duplicate
partition.add(new FactorSet(subsetTotal,otherSubsetTotal));
}
}

Of course, the first thing to do is find the prime factorisation of the number, like glowcoder said. Say
n = p^a * q^b * r^c * ...
Then
find the multiplicative partitions of m = n / p^a
for 0 <= k <= a, find the multiplicative partitions of p^k, which is equivalent to finding the additive partitions of k
for each multiplicative partition of m, find all distinct ways to distribute a-k factors p among the factors
combine results of 2. and 3.
It is convenient to treat the multiplicative partitions as lists (or sets) of (divisor, multiplicity) pairs to avoid producing duplicates.
I've written the code in Haskell because it's the most convenient and concise of the languages I know for this sort of thing:
module MultiPart (multiplicativePartitions) where
import Data.List (sort)
import Math.NumberTheory.Primes (factorise)
import Control.Arrow (first)
multiplicativePartitions :: Integer -> [[Integer]]
multiplicativePartitions n
| n < 1 = []
| n == 1 = [[]]
| otherwise = map ((>>= uncurry (flip replicate)) . sort) . pfPartitions $ factorise n
additivePartitions :: Int -> [[(Int,Int)]]
additivePartitions 0 = [[]]
additivePartitions n
| n < 0 = []
| otherwise = aParts n n
where
aParts :: Int -> Int -> [[(Int,Int)]]
aParts 0 _ = [[]]
aParts 1 m = [[(1,m)]]
aParts k m = withK ++ aParts (k-1) m
where
withK = do
let q = m `quot` k
j <- [q,q-1 .. 1]
[(k,j):prt | let r = m - j*k, prt <- aParts (min (k-1) r) r]
countedPartitions :: Int -> Int -> [[(Int,Int)]]
countedPartitions 0 count = [[(0,count)]]
countedPartitions quant count = cbParts quant quant count
where
prep _ 0 = id
prep m j = ((m,j):)
cbParts :: Int -> Int -> Int -> [[(Int,Int)]]
cbParts q 0 c
| q == 0 = if c == 0 then [[]] else [[(0,c)]]
| otherwise = error "Oops"
cbParts q 1 c
| c < q = [] -- should never happen
| c == q = [[(1,c)]]
| otherwise = [[(1,q),(0,c-q)]]
cbParts q m c = do
let lo = max 0 $ q - c*(m-1)
hi = q `quot` m
j <- [lo .. hi]
let r = q - j*m
m' = min (m-1) r
map (prep m j) $ cbParts r m' (c-j)
primePowerPartitions :: Integer -> Int -> [[(Integer,Int)]]
primePowerPartitions p e = map (map (first (p^))) $ additivePartitions e
distOne :: Integer -> Int -> Integer -> Int -> [[(Integer,Int)]]
distOne _ 0 d k = [[(d,k)]]
distOne p e d k = do
cap <- countedPartitions e k
return $ [(p^i*d,m) | (i,m) <- cap]
distribute :: Integer -> Int -> [(Integer,Int)] -> [[(Integer,Int)]]
distribute _ 0 xs = [xs]
distribute p e [(d,k)] = distOne p e d k
distribute p e ((d,k):dks) = do
j <- [0 .. e]
dps <- distOne p j d k
ys <- distribute p (e-j) dks
return $ dps ++ ys
distribute _ _ [] = []
pfPartitions :: [(Integer,Int)] -> [[(Integer,Int)]]
pfPartitions [] = [[]]
pfPartitions [(p,e)] = primePowerPartitions p e
pfPartitions ((p,e):pps) = do
cop <- pfPartitions pps
k <- [0 .. e]
ppp <- primePowerPartitions p k
mix <- distribute p (e-k) cop
return (ppp ++ mix)
It's not particularly optimised, but it does the job.
Some times and results:
Prelude MultiPart> length $ multiplicativePartitions $ 10^10
59521
(0.03 secs, 53535264 bytes)
Prelude MultiPart> length $ multiplicativePartitions $ 10^11
151958
(0.11 secs, 125850200 bytes)
Prelude MultiPart> length $ multiplicativePartitions $ 10^12
379693
(0.26 secs, 296844616 bytes)
Prelude MultiPart> length $ multiplicativePartitions $ product [2 .. 10]
70520
(0.07 secs, 72786128 bytes)
Prelude MultiPart> length $ multiplicativePartitions $ product [2 .. 11]
425240
(0.36 secs, 460094808 bytes)
Prelude MultiPart> length $ multiplicativePartitions $ product [2 .. 12]
2787810
(2.06 secs, 2572962320 bytes)
The 10^k are of course particularly easy because there are only two primes involved (but squarefree numbers are still easier), the factorials get slow earlier. I think by careful organisation of the order and choice of better data structures than lists, there's quite a bit to be gained (probably one should sort the prime factors by exponent, but I don't know whether one should start with the highest exponents or the lowest).

Why dont you find all the numbers that can divide the number and then you find permutations of the numbers that multiplications will add up to the number?
Finding all numbers that can divide your number takes O(n).
Then you can permute this set to find all possible sets that multiplication of this set will give you the number.
Once you find set of all possible numbers that divide the original number, then you can do dynamic programming on them to find the set of numbers that multiplying them will give you the original number.

Related

How to find the count of numbers which are divisible by 7?

Given an integer N, how to efficiently find the count of numbers which are divisible by 7 (their reverse should also be divisible by 7) in the range:
[0, 10^N - 1]
Example:
For N=2, answer:
4 {0, 7, 70, 77}
[All numbers from 0 to 99 which are divisible by 7 (also their reverse is divisible)]
My approach, simple brute-force:
initialize count to zero
run a loop from i=0 till end
if a(i) % 7 == 0 && reverse(a(i)) % 7 == 0, then we increase the count
Note:
reverse(123) = 321, reverse(1200) = 21, for example!
Let's see what happens mod 7 when we add a digit, d, to a prefix, abc.
10 * abc + d =>
(10 mod 7 * abc mod 7) mod 7 + d mod 7
reversed number:
abc + d * 10^(length(prefix) =>
abc mod 7 + (d mod 7 * 10^3 mod 7) mod 7
Note is that we only need the count of prefixes of abc mod 7 for each such remainder, not the actual prefixes.
Let COUNTS(n,f,r) be the number of n-digit numbers such that n%7 = f and REVERSE(n)%7 = r
The counts are easy to calculate for n=1:
COUNTS(1,f,r) = 0 when f!=r, since a 1-digit number is the same as its reverse.
COUNTS(1,x,x) = 1 when x >= 3, and
COUNTS(1,x,x) = 2 when x < 3, since 7%3=0, 8%3=1, and 9%3=2
The counts for other lengths can be figured out by calculating what happens when you add each digit from 0 to 9 to the numbers characterized by the previous counts.
At the end, COUNTS(N,0,0) is the answer you are looking for.
In python, for example, it looks like this:
def getModCounts(len):
counts=[[0]*7 for i in range(0,7)]
if len<1:
return counts
if len<2:
counts[0][0] = counts[1][1] = counts[2][2] = 2
counts[3][3] = counts[4][4] = counts[5][5] = counts[6][6] = 1
return counts
prevCounts = getModCounts(len-1)
for f in range(0,7):
for r in range(0,7):
c = prevCounts[f][r]
rplace=(10**(len-1))%7
for newdigit in range(0,10):
newf=(f*10 + newdigit)%7
newr=(r + newdigit*rplace)%7
counts[newf][newr]+=c
return counts
def numFwdAndRevDivisible(len):
return getModCounts(len)[0][0]
#TEST
for i in range(0,20):
print("{0} -> {1}".format(i, numFwdAndRevDivisible(i)))
See if it gives the answers you're expecting. If not, maybe there's a bug I need to fix:
0 -> 0
1 -> 2
2 -> 4
3 -> 22
4 -> 206
5 -> 2113
6 -> 20728
7 -> 205438
8 -> 2043640
9 -> 20411101
10 -> 204084732
11 -> 2040990205
12 -> 20408959192
13 -> 204085028987
14 -> 2040823461232
15 -> 20408170697950
16 -> 204081640379568
17 -> 2040816769367351
18 -> 20408165293673530
19 -> 204081641308734748
This is a pretty good answer when counting up to N is reasonable -- way better than brute force, which counts up to 10^N.
For very long lengths like N=10^18 (you would probably be asked for a the count mod 1000000007 or something), there is a next-level answer.
Note that there is a linear relationship between the counts for length n and the counts for length n+1, and that this relationship can be represented by a 49x49 matrix. You can exponentiate this matrix to the Nth power using exponentiation by squaring in O(log N) matrix multiplications, and then just multiply by the single digit counts to get the length N counts.
There is a recursive solution using digit dp technique for any digits.
long long call(int pos , int Mod ,int revMod){
if(pos == len ){
if(!Mod && !revMod)return 1;
return 0;
}
if(dp[pos][Mod][revMod] != -1 )return dp[pos][Mod][revMod] ;
long long res =0;
for(int i= 0; i<= 9; i++ ){
int revValue =(base[pos]*i + revMod)%7;
int curValue = (Mod*10 + i)%7;
res += call(pos+1, curValue,revValue) ;
}
return dp[pos][Mod][revMod] = res ;
}

Is there any way of optimizing a multiplication loop?

Let's say I have to repeat the process of multiplying a variable by a constant and modulus the result by another constant, n times to get my desired result.
the obvious solution is iterating n times, but it's getting time consuming the greater n is.
Code example:
const N = 1000000;
const A = 123;
const B = 456;
var c = 789;
for (var i = 0; i < n; i++)
{
c = (c * a) % b;
}
log("Total: " + c);
Is there any algebraic solution to optimize this loop?
% has two useful properties:
1) (x % b) % b = x % b
2) (c*a) % b = ((c%b) * (a%b))%b
This implies that e.g.
(((c*a)%b)*a) % b = ((((c*a)%b)%b) * (a%b)) % b
= (((c*a) % b) * (a%b)) % b
= (c*a*a) % b
= (c*a^2) % b
Hence, in your case the final c that you compute is equivalent to
(c*a^n)%b
This can be computed efficiently using exponentiation by squaring.
To illustrate this equivalence:
def f(a,b,c,n):
for i in range(n):
c = (c*a)%b
return c
def g(a,b,c,n):
return (c*pow(a,n,b)) % b
a = 123
b = 456
c = 789
n = 10**6
print(f(a,b,c,n),g(a,b,c,n)) #prints 261, 261
First, note that c * A^n is never an exact multiple of B = 456 since the former is always odd and the latter is always even. You can generalize this by considering the prime factorizations of the numbers involved and see that no repetition of the factors of c and A will ever give you something that contains all the factors of B. This means c will never turn into 0 as a result of the iterated multiplication.
There are only 456 possible values for c * a mod B = 456; therefore, if you iterate the loop 456 times, you will see at least value of c repeated. Suppose the first value of c that repeats is c', when i= i'. Say it first saw c' when i=i''. By continuing to iterate the multiplication, we would expect to see c' again:
we saw it at i''
we saw it at i'
we should see it at i' + (i' - i'')
we should see it at i' + k(i' - i'') as well
Once you detect a repeat you know that pattern is going to repeat forever. Therefore, you can compute how many patterns are needed to get to N, and the offset in the repeating pattern that you'd be at for i = N - 1, and then you'd know the answer without actually performing the multiplications.
A simpler example:
A = 2
B = 3
C = 5
c[0] = 5
c[1] = 5 * 2 % 3 = 1
c[2] = 1 * 2 % 3 = 2
c[3] = 2 * 2 % 3 = 1 <= duplicate
i' = 3
i'' = 1
repeating pattern: 1, 2, 1
c[1+3k] = 1
c[2+3k] = 2
c[3+3k] = 1
10,000 = 1 + 3k for k = 3,333
c[10,000] = 1
c[10,001] = 2
c[10,002] = 1

Finding the largest power of a number that divides a factorial in haskell

So I am writing a haskell program to calculate the largest power of a number that divides a factorial.
largestPower :: Int -> Int -> Int
Here largestPower a b has find largest power of b that divides a!.
Now I understand the math behind it, the way to find the answer is to repeatedly divide a (just a) by b, ignore the remainder and finally add all the quotients. So if we have something like
largestPower 10 2
we should get 8 because 10/2=5/2=2/2=1 and we add 5+2+1=8
However, I am unable to figure out how to implement this as a function, do I use arrays or just a simple recursive function.
I am gravitating towards it being just a normal function, though I guess it can be done by storing quotients in an array and adding them.
Recursion without an accumulator
You can simply write a recursive algorithm and sum up the result of each call. Here we have two cases:
a is less than b, in which case the largest power is 0. So:
largestPower a b | a < b = 0
a is greater than or equal to b, in that case we divide a by b, calculate largestPower for that division, and add the division to the result. Like:
| otherwise = d + largestPower d b
where d = (div a b)
Or putting it together:
largestPower a b | a < b = 1
| otherwise = d + largestPower d b
where d = (div a b)
Recursion with an accumuator
You can also use recursion with an accumulator: a variable you pass through the recursion, and update accordingly. At the end, you return that accumulator (or a function called on that accumulator).
Here the accumulator would of course be the running product of divisions, so:
largestPower = largestPower' 0
So we will define a function largestPower' (mind the accent) with an accumulator as first argument that is initialized as 1.
Now in the recursion, there are two cases:
a is less than b, we simply return the accumulator:
largestPower' r a b | a < b = r
otherwise we multiply our accumulator with b, and pass the division to the largestPower' with a recursive call:
| otherwise = largestPower' (d+r) d b
where d = (div a b)
Or the full version:
largestPower = largestPower' 1
largestPower' r a b | a < b = r
| otherwise = largestPower' (d+r) d b
where d = (div a b)
Naive correct algorithm
The algorithm is not correct. A "naive" algorithm would be to simply divide every item and keep decrementing until you reach 1, like:
largestPower 1 _ = 0
largestPower a b = sumPower a + largestPower (a-1) b
where sumPower n | n `mod` b == 0 = 1 + sumPower (div n b)
| otherwise = 0
So this means that for the largestPower 4 2, this can be written as:
largestPower 4 2 = sumPower 4 + sumPower 3 + sumPower 2
and:
sumPower 4 = 1 + sumPower 2
= 1 + 1 + sumPower 1
= 1 + 1 + 0
= 2
sumPower 3 = 0
sumPower 2 = 1 + sumPower 1
= 1 + 0
= 1
So 3.
The algorithm as stated can be implemented quite simply:
largestPower :: Int -> Int -> Int
largestPower 0 b = 0
largestPower a b = d + largestPower d b where d = a `div` b
However, the algorithm is not correct for composite b. For example, largestPower 10 6 with this algorithm yields 1, but in fact the correct answer is 4. The problem is that this algorithm ignores multiples of 2 and 3 that are not multiples of 6. How you fix the algorithm is a completely separate question, though.

Algorithm for checking if number is factorable into a set of prime numbers

I was wondering if there is an algorithm that checks wether a given number is factorable into a set of prime numbers and if no give out the nearest number.
The problem comes always up when I use the FFT.
Thanks a lot for your help guys.
In general this looks like a hard problem, particularly finding the next largest integer that factors into your set of primes. However, if your set of primes isn't too big, one approach would be to turn this into an integer optimization problem by taking the logs. Here is how to find the smallest number > n that factors into a set of primes p_1...p_k
choose integers x_1,...,x_k to minimize (x_1 log p_1 + ... + x_k log p_k - log n)
Subject to:
x_1 log p_1 + ... + x_k log p_k >= log n
x_i >= 0 for all i
The x_i will give you the exponents for the primes. Here is an implementation in R using lpSolve:
minfact<-function(x,p){
sol<-lp("min",log(p),t(log(p)),">=",log(x),all.int=T)
prod(p^sol$solution)
}
> p<-c(2,3,13,31)
> x<-124363183
> y<-minfact(x,p)
> y
[1] 124730112
> factorize(y)
Big Integer ('bigz') object of length 13:
[1] 2 2 2 2 2 2 2 2 3 13 13 31 31
> y-x
[1] 366929
>
Using big integers, this works pretty well even for large numbers:
> p<-c(2,3,13,31,53,79)
> x<-as.bigz("1243631831278461278641361")
> y<-minfact(x,p)
y
>
Big Integer ('bigz') :
[1] 1243634072805560436129792
> factorize(y)
Big Integer ('bigz') object of length 45:
[1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
[26] 2 2 2 2 2 2 2 2 3 3 3 3 13 31 31 31 31 53 53 53
>
Your question is about well-known factorization problem - which could not be resolved with 'fast' (polynomial) time. Lenstra's elliptic algorithm is the most efficient (known) way in common case, but it requires strong knowledge of numbers theory - and it's also sub-exponential (but not polynomial).
Other algorithms are listed in the page by first link in my post, but such things as direct try (brute force) are much more slower, of cause.
Please, note, that under "could not be resolved with polynomial time" - I mean that there's no way to do this now - but not that such way does not exist (at least now, number theory can not provide such solution for this problem)
Here is a brute force method in C++. It returns the factorization of the nearest factorable number. If N has two equidistant factorable neighbours, it returns the smallest one.
GCC 4.7.3: g++ -Wall -Wextra -std=c++0x factorable-neighbour.cpp
#include <iostream>
#include <vector>
using ints = std::vector<int>;
ints factor(int n, const ints& primes) {
ints f(primes.size(), 0);
for (int i = 0; i < primes.size(); ++i) {
while (0< n && !(n % primes[i])) {
n /= primes[i];
++f[i]; } }
// append the "remainder"
f.push_back(n);
return f;
}
ints closest_factorable(int n, const ints& primes) {
int d = 0;
ints r;
while (true) {
r = factor(n + d, primes);
if (r[r.size() - 1] == 1) { break; }
++d;
r = factor(n - d, primes);
if (r[r.size() - 1] == 1) { break; }
}
r.pop_back();
return r; }
int main() {
for (int i = 0; i < 30; ++i) {
for (const auto& f : closest_factorable(i, {2, 3, 5, 7, 11})) {
std::cout << f << " "; }
std::cout << "\n"; }
}
I suppose that you have a (small) set of prime numbers S and an integer n and you want to know is n factors only using number in S. The easiest way seems to be the following:
P <- product of s in S
while P != 1 do
P <- GCD(P, n)
n <- n/P
return n == 1
You compute the GCD using Euclid's algorithm.
The idea is the following: Suppose that S = {p1, p2, ... ,pk}. You can write n uniquely as
n = p1^n1 p2^n2 ... pk^nk * R
where R is coprime wrt the pi. You want to know whether R=1.
Then
GCD(n, P) = prod ( pi such that ni <> 0 ).
Therefore n/p decrease all those non zeros ni by 1 so that they eventually become 0. At the end only R remains.
For example: S = {2,3,5}, n = 5600 = 2^5*5^2*7. Then P = 2*3*5 = 30. One gets GCD(n, p)=10=2*5. And therefore n/GCD(n,p) = 560 = 2^4*5*7.
You are now back to the same problem: You want to know if 560 can be factored using S = {2,5} hence the loop. So the next steps are
GCD(560, 10) = 10. 560/GCD = 56 = 2^3 * 7.
GCD(56, 10) = 2. 56/2 = 28 = 2^2 * 7
GCD(28, 2) = 2. 28/2 = 14 = 2 * 7
GCD(14, 2) = 2. 14/2 = 7
GCD(7, 2) = 1 so that R = 7 ! Your answer if FALSE.
kissfft has a function
int kiss_fft_next_fast_size(int n)
that returns the next largest N that is an aggregate of 2,3,5.
Also related is a kf_factor function that factorizes a number n, pulling out the "nice" FFT primes first (e.g. 4's are pulled out before 2's)

How to decompose an integer in two for grid creation

Given an integer N I want to find two integers A and B that satisfy A × B ≥ N with the following conditions:
The difference between A × B and N is as low as possible.
The difference between A and B is as low as possible (to approach a square).
Example: 23. Possible solutions 3 × 8, 6 × 4, 5 × 5. 6 × 4 is the best since it leaves just one empty space in the grid and is "less" rectangular than 3 × 8.
Another example: 21. Solutions 3 × 7 and 4 × 6. 3 × 7 is the desired one.
A brute force solution is easy. I would like to see if a clever solution is possible.
Easy.
In pseudocode
a = b = floor(sqrt(N))
if (a * b >= N) return (a, b)
a += 1
if (a * b >= N) return (a, b)
return (a, b+1)
and it will always terminate, the distance between a and b at most only 1.
It will be much harder if you relax second constraint, but that's another question.
Edit: as it seems that the first condition is more important, you have to attack the problem
a bit differently. You have to specify some method to measure the badness of not being square enough = 2nd condition, because even prime numbers can be factorized as 1*number, and we fulfill the first condition. Assume we have a badness function (say a >= b && a <= 2 * b), then factorize N and try different combinations to find best one. If there aren't any good enough, try with N+1 and so on.
Edit2: after thinking a bit more I come with this solution, in Python:
from math import sqrt
def isok(a, b):
"""accept difference of five - 2nd rule"""
return a <= b + 5
def improve(a, b, N):
"""improve result:
if a == b:
(a+1)*(b-1) = a^2 - 1 < a*a
otherwise (a - 1 >= b as a is always larger)
(a+1)*(b-1) = a*b - a + b - 1 =< a*b
On each iteration new a*b will be less,
continue until we can, or 2nd condition is still met
"""
while (a+1) * (b-1) >= N and isok(a+1, b-1):
a, b = a + 1, b - 1
return (a, b)
def decomposite(N):
a = int(sqrt(N))
b = a
# N is square, result is ok
if a * b >= N:
return (a, b)
a += 1
if a * b >= N:
return improve(a, b, N)
return improve(a, b+1, N)
def test(N):
(a, b) = decomposite(N)
print "%d decomposed as %d * %d = %d" % (N, a, b, a*b)
[test(x) for x in [99, 100, 101, 20, 21, 22, 23]]
which outputs
99 decomposed as 11 * 9 = 99
100 decomposed as 10 * 10 = 100
101 decomposed as 13 * 8 = 104
20 decomposed as 5 * 4 = 20
21 decomposed as 7 * 3 = 21
22 decomposed as 6 * 4 = 24
23 decomposed as 6 * 4 = 24
I think this may work (your conditions are somewhat ambiguous). this solution is somewhat similar to other one, in basically produces rectangular matrix which is almost square.
you may need to prove that A+2 is not optimal condition
A0 = B0 = ceil (sqrt N)
A1 = A0+1
B1 = B0-1
if A0*B0-N > A1*B1-N: return (A1,B1)
return (A0,B0)
this is solution if first condition is dominant (and second condition is not used)
A0 = B0 = ceil (sqrt N)
if A0*B0==N: return (A0,B0)
return (N,1)
Other conditions variations will be in between
A = B = ceil (sqrt N)

Resources