Count integer partions with k parts, each below some threshold m - algorithm

I want to count the number of ways we can partition the number n, into k distinct parts where each part is not larger than m.
For k := 2 i have following algorithm:
public int calcIntegerPartition(int n, int k, int m) {
int cnt=0;
for(int i=1; i <= m;i++){
for(int j=i+1; j <= m; j++){
if(i+j == n){
cnt++;
break;
}
}
}
return cnt;
}
But how can i count integer partitions with k > 2? Usually I have n > 100000, k := 40, m < 10000.
Thank you in advance.

Let's start by choosing the k largest legal numbers: m, m-1, m-2, ..., m-(k-1). This adds up to k*m - k(k-1)/2. If m < k, there are no solutions because the smallest partition would be <= 0. Let's assume m >= k.
Let's say p = (km - k(k-1)/2) - n.
If p < 0, there are no solutions because the largest number we can make is less than n. Let's assume p >= 0. Note that if p = 0 there is exactly one solution, so let's assume p > 0.
Now, imagine we start by choosing the k largest distinct legal integers, and we then correct this to get a solution. Our correction involves moving values to the left (on the number line) 1 slot, into empty slots, exactly p times. How many ways can we do this?
The smallest value to start with is m-(k-1), and it can move as far down as 1, so up to m-k times. After this, each successive value can move up to its predecessor's move.
Now the problem is, how many nonincreasing integer sequences with a max value of m-k sum to p? This is the partition problem. I.e., how many ways can we partition p (into at most k partitions). This is no closed-form solution to this.
Someone has already written up a nice answer of this problem here (which will need slight modification to meet your restrictions):
Is there an efficient algorithm for integer partitioning with restricted number of parts?

As #Dave alludes to, there is already a really nice answer to the simple restricted integer case (found here (same link as #Dave): Is there an efficient algorithm for integer partitioning with restricted number of parts?).
Below is a variant in C++ which takes into account the maximum value of each restricted part. First, here is the workhorse:
#include <vector>
#include <algorithm>
#include <iostream>
int width;
int blockSize;
static std::vector<double> memoize;
double pStdCap(int n, int m, int myMax) {
if (myMax * m < n || n < m) return 0;
if (myMax * m == n || n <= m + 1) return 1;
if (m < 2) return m;
const int block = myMax * blockSize + (n - m) * width + m - 2;
if (memoize[block]) return memoize[block];
int niter = n / m;
if (m == 2) {
if (myMax * 2 >= n) {
myMax = std::min(myMax, n - 1);
return niter - (n - 1 - myMax);
} else {
return 0;
}
}
double count = 0;
for (; niter--; n -= m, --myMax) {
count += (memoize[myMax * blockSize + (n - m) * width + m - 3] = pStdCap(n - 1, m - 1, myMax));
}
return count;
}
As you can see pStdCap is very similar to the linked solution. The one noticeable difference are the 2 additional checks at the top:
if (myMax * m < n || n < m) return 0;
if (myMax * m == n || n <= m + 1) return 1;
And here is the function that sets up the recursion:
double CountPartLenCap(int n, int m, int myMax) {
if (myMax * m < n || n < m) return 0;
if (myMax * m == n || n <= m + 1) return 1;
if (m < 2) return m;
if (m == 2) {
if (myMax * 2 >= n) {
myMax = std::min(myMax, n - 1);
return n / m - (n - 1 - myMax);
} else {
return 0;
}
}
width = m;
blockSize = m * (n - m + 1);
memoize = std::vector<double>((myMax + 1) * blockSize, 0.0);
return pStdCap(n, m, myMax);
}
Explanation of the parameters:
n is the integer that you are partitioning
m is the length of each partition
myMax is the maximum value that can appear in a given partition. (the OP refers to this as the threshold)
Here is a live demonstration https://ideone.com/c3WohV
And here is a non memoized version of pStdCap which is a bit easier to understand. This is originally found in this answer to Is there an efficient way to generate N random integers in a range that have a given sum or average?
int pNonMemoStdCap(int n, int m, int myMax) {
if (myMax * m < n) return 0;
if (myMax * m == n) return 1;
if (m < 2) return m;
if (n < m) return 0;
if (n <= m + 1) return 1;
int niter = n / m;
int count = 0;
for (; niter--; n -= m, --myMax) {
count += pNonMemoStdCap(n - 1, m - 1, myMax);
}
return count;
}
If you actually intend to calculate the number of partitions for numbers as large as 10000, you are going to need a big int library as CountPartLenCap(10000, 40, 300) > 3.2e37 (Based off the OP's requirement).

Related

How to count the numbers that are divisible by their sum of digits?

Following is a question from hackerearth.
here's the link to the problem
problem!
I coded its solution in java and c but got time limit exceeded for some test cases on submission. No participant was able to solve this for all test cases. What is the most efficient solution for this?
QUESTION:
Bob likes DSD Numbers. DSD Number is a number which is divisible by its
Digit Sum in Decimal Representation.
digitSum(n) : Sum of digits of n (in Decimal Representation)
eg: n = 1234 then digitSum(n) = 1 + 2 + 3 + 4 = 10
DSD Number is number n such that n % digitSum(n) equal to 0
Bob asked Alice to tell the number of DSD Numbers in range [L,R]
inclusive.
Constraints:
1 <= test cases <= 50
1<=L<=R<=10^9
Sample Input
4
2 5
1 10
20 45
1 100
Sample Output
4
10
9
33
Code in Java:
class DSD {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
int t=Integer.parseInt(br.readLine());
while(t-->0){
StringTokenizer st=new StringTokenizer(br.readLine());
int L=Integer.parseInt(st.nextToken());
int R=Integer.parseInt(st.nextToken());
int count=0,sum=0,i=L,j=0;
while(i>0){
sum+=i%10;
i=i/10;
}
if(L%sum==0)
count++;
for(i=L+1;i<=R;i++){
if(i%10!=0){
sum+=1;
}
else
{
j=i;
while(j%10==0){
sum-=9;
j/=10;
}
sum+=1;
}
if(i%sum==0)
count++;
}
out.println(count);
}
out.close();
}
}
We can solve this problem by using dynamic programming.
Observation:
There will be maximum 10 digits for each number, so the maximum sum of digit for each number will be less than 100.
So, assuming that we know the sum of digit for one number, by processing digit by digit, we have four things to check:
Whether the current number is larger than the lower bound.
Whether the current number is smaller than the upper bound.
What is the mod of current number with its sum.
What is the current sum of all digits.
We come up with this function int count(int digit, boolean larger, boolean smaller, int left, int mod), and then, the dp state: dp[digit][larger][smaller][left][mod].
For each test case, time complexity is number of possible sum^3 x number of digit = 100^3*10 = 10^7.
There is 50 test cases -> 50*10^7 = 5*10^8 operations, which still be in the time limit.
Java code:
static int[][][][][] dp;
static int[][][][][] check;
static int cur = 0;
public static void main(String[] args) throws FileNotFoundException {
// PrintWriter out = new PrintWriter(new FileOutputStream(new File(
// "output.txt")));
PrintWriter out = new PrintWriter(System.out);
Scanner in = new Scanner();
int n = in.nextInt();
dp = new int[11][2][2][82][82];
check = new int[11][2][2][82][82];
for (int i = 0; i < n; i++) {
int l = in.nextInt();
int r = in.nextInt();
String L = "" + l;
String R = "" + r;
while (L.length() < R.length()) {
L = "0" + L;
}
int result = 0;
for (int j = 1; j <= 81; j++) {
cur = cur + 1;
result += count(0, 0, 0, j, 0, j, L, R);
}
out.println(result);
}
out.close();
}
public static int count(int index, int larger, int smaller, int left,
int mod, int sum, String L, String R) {
if (index == L.length()) {
if (left == 0 && mod == 0) {
return 1;
}
return 0;
}
if((L.length() - index) * 9 < left){
return 0;
}
if (check[index][larger][smaller][left][mod] == cur) {
return dp[index][larger][smaller][left][mod];
}
//System.out.println(cur);
check[index][larger][smaller][left][mod] = cur;
int x = L.charAt(index) - '0';
int y = R.charAt(index) - '0';
int result = 0;
for (int i = 0; i < 10 && i <= left; i++) {
if (x > i && larger == 0) {
continue;
}
if (y < i && smaller == 0) {
continue;
}
int nxtLarger = larger;
int nxtSmaller = smaller;
if (x < i) {
nxtLarger = 1;
}
if (y > i) {
nxtSmaller = 1;
}
int nxtMod = (mod * 10 + i) % sum;
result += count(index + 1, nxtLarger, nxtSmaller, left - i, nxtMod,
sum, L, R);
}
return dp[index][larger][smaller][left][mod] = result;
}
Update: I have submitted and passed all the test cases for this problem, (2nd person who solved this) This is the link of my submission
Let f (L, R) = "number of integers L ≤ x ≤ R where x is divisible by the sum of its digits". We define that x = 0 is not counted.
Let g (M) = "number of integers 1 ≤ x < M where x is divisible by the sum of its digits". We have f (L, R) = g (R + 1) - g (L).
Find the largest k ≥ 0 such that 10^k <= M. Find the largest a ≥ 1 such that a * 10^k <= M. All integers < M have at most 9k + (a-1) as sum of digits.
Let h (M, n) = "number of integers 1 ≤ x < M where x is divisible by n, and the sum of digits is n". g (M) is the sum of h (M, n) for 1 ≤ n ≤ 9*k + (a - 1).
Let r (a, k, n) = "number of integers a*10^k ≤ x < (a+1)*10^k where x is divisible by n, and the sum of digits is n". h (M, n) can be calculated by adding values of r (a, k, n) in an obvious way; for example:
h (1,234,000,000, n) = r (0, 9, n) + r (10, 8, n) + r (11, 8, n) + r (120, 7, n) + r (121, 7, n) + r (122, 7, n) + r (1230, 6, n) + r (1231, 6, n) + r (1232, 6, n) + r (1233, 6, n).
Let f (k, n, d, m) = "number of integers 0 ≤ x < 10^k where the sum of digits is d, and x % n = m". We can calculate r (a, k, n) using this function: The last k digits must have a digit sum of n - digitsum (a). If the whole number is divisible by n, then the last k digits must have a remainder of (- a*10^k) % n. So r (a, k, n) = f (k, n, n - digitsum(a), - (a*10^k) % n).
f (k, n, d, m) is trivial if k = 1: Only for the number d is the sum of digits equal to d, so f (1, n, d, m) is 1 if d % n = m, and 0 otherwise.
To calculate f (k+1, n, d, m) we add f (k, n, d-a, (m - a*10^k)%n) for 0 ≤ a ≤ 9. Obviously all the values f (k, n, d, m) must be stored so they are not recalculated again and again.
And that's it. How many operations: If R < 10^r, then numbers have up to 9r digits. We calculate values f (k, n, d, m) for 1 ≤ k ≤ r, for 1 ≤ n ≤ 9r, for 0 ≤ d ≤ 9r, for 0 ≤ m < n. For each of those we add 10 different numbers, so we have less than 10,000 r^4 additions. So numbers up to 10^19 are no problem.
The following approach should take about 10^7 operations per case.
Split numbers into a prefix (n/10000) and a suffix (n%10000). Once you choose a digit sum, only a little data from each of the prefix and suffix are needed to determine if the digit sum divides the number. (This is related to some things gnasher729 said, but I get a much different running time.)
For each possible digit sum d from 1 to 81,
Map prefix p to a pair (p*10000 % d, digit sum(p)).
Tally the counts in a matrix M.
Map each possible suffix s to a pair (s % d, digit sum(s)).
Tally the counts in a matrix N.
For every (a,b),
total += M[a,b] *N[-a%d,d-b]
There are about 81 * (10^5 + 10^4) steps.
The edge cases where a prefix is partially allowed (L/10000, R/10000, and 100000) can be brute-forced in about 20000 steps once.
Interesting problem. Straightforward solution would be to iterate through the numbers from L to R, calculate the sum of digits for each, and check for each whether the number is divisible by the sum of digits.
Calculating the sum of digits can be made faster obviously. The numbers xxx0, xxx1, xxx2, ..., xxx9 have digit sums n, n+1, n+2, ..., n+9. So for ten consecutive numbers almost no effort is needed to calculate the digit sum, just a modulo operation to check for divisibility.
The modulo check can be made faster. Compilers use clever tricks to divide by constants, replacing a slow division with a shift and a multiplication. You can search for how this is done, and since there are only 81 possible divisors, do at runtime what the compiler would do for constants. That should get the time down to few nanoseconds per number.
To do better: I'd make a loop checking for numbers with digit sum 1, digit sum 2, etc. As an example, assume I'm checking numbers with digit sum 17. These numbers must have a digit sum of 17, and also be multiples of 17. I take the numbers from 0000 to 9999 and for each I calculate the sum of digits, and the value modulo 17, and divide them into 37 x 17 sets where all the numbers in the set have the same digit sum and the same value modulo 17 and count the elements in each set.
Then to check the numbers from 0 to 9999: I pick the set where the digit sum is 17, and the value modulo 17 is 0 and take the element count of that set. To check numbers from 10,000 to 19,999: I pick the set where the digit sum is 16, and the value modulo 17 is 13 (because 10013 is divisible by 17), and so on.
That's just the idea. I think with a bit of cleverness that can be extended to a method that takes O (log^4 R) steps to handle all the numbers from L to R.
In the C code below, I have focused on the core portion, i.e. finding the DSD count. The code is admittedly ugly, but that's what you get when coding in a hurry.
The basic observation is that the digit sum can be simplified by tracking the digits of the number individually, reducing the digit sum determination to simple increments/decrements in each step. There are probably clever ways to accelerate the modulo computations, I could not come up with any on the double.
On my machine (Xeon E3 1270 v2, 3.5 GHz) the code below finds the count of DSDs in [1,1e9] in 3.54 seconds. I compiled with MSVC 2010 at optimization level -O2. While you stated a time limit of 1 second in an update to your question, it is not clear that this extreme case is exercised by the framework at the website you mentioned. In any event this will provide a reasonable baseline to compare other proposed solutions against.
#include <stdio.h>
#include <stdlib.h>
/* sum digits in decimal representation of x */
int digitsum (int x)
{
int sum = 0;
while (x) {
sum += x % 10;
x = x / 10;
}
return sum;
}
/* split integer into individual decimal digits. p[0]=ones, p[1]=tens, ... */
void split (int a, int *p)
{
int i = 0;
while (a) {
p[i] = a % 10;
a = a / 10;
i++;
}
}
/* return number of DSDs in [first,last] inclusive. first, last in [1,1e9] */
int count_dsd (int first, int last)
{
int num, ds, count = 0, p[10] = {0};
num = first;
split (num, p);
ds = digitsum (num);
while (p[9] < 10) {
while (p[8] < 10) {
while (p[7] < 10) {
while (p[6] < 10) {
while (p[5] < 10) {
while (p[4] < 10) {
while (p[3] < 10) {
while (p[2] < 10) {
while (p[1] < 10) {
while (p[0] < 10) {
count += ((num % ds) == 0);
if (num == last) {
return count;
}
num++;
p[0]++;
ds++;
}
p[0] = 0;
p[1]++;
ds -= 9;
}
p[1] = 0;
p[2]++;
ds -= 9;
}
p[2] = 0;
p[3]++;
ds -= 9;
}
p[3] = 0;
p[4]++;
ds -= 9;
}
p[4] = 0;
p[5]++;
ds -= 9;
}
p[5] = 0;
p[6]++;
ds -= 9;
}
p[6] = 0;
p[7]++;
ds -= 9;
}
p[7] = 0;
p[8]++;
ds -= 9;
}
p[8] = 0;
p[9]++;
ds -= 9;
}
return count;
}
int main (void)
{
int i, first, last, *count, testcases;
scanf ("%d", &testcases);
count = malloc (testcases * sizeof(count[0]));
if (!count) return EXIT_FAILURE;
for (i = 0; i < testcases; i++) {
scanf ("%d %d", &first, &last);
count[i] = count_dsd (first, last);
}
for (i = 0; i < testcases; i++) {
printf ("%d\n", count[i]);
}
free (count);
return EXIT_SUCCESS;
}
I copied the sample inputs stated in the question into a text file testdata, and when I call the executable like so:
dsd < testdata
the output is as desired:
4
10
9
33
Solution in Java
Implement a program to find out whether a number is divisible by the sum of its digits.
Display appropriate messages.
class DivisibleBySum
{
public static void main(String[] args)
{
// Implement your code here
int num = 123;
int number = num;
int sum=0;
for(;num>0;num /=10)
{
int rem = num % 10;
sum += rem;
}
if(number %sum ==0)
System.out.println(number+" is divisible by sum of its digits");
else
System.out.println(number+" is not divisible by sum of its digits");
}
}

How many numbers with length N with K digits D consecutively

Given positive numbers N, K, D (1<= N <= 10^5, 1<=K<=N, 1<=D<=9). How many numbers with N digits are there, that have K consecutive digits D? Write the answer mod (10^9 + 7).
For example: N = 4, K = 3, D = 6, there are 18 numbers:
1666, 2666, 3666, 4666, 5666, 6660,
6661, 6662, 6663, 6664, 6665, 6666, 6667, 6668, 6669, 7666, 8666 and 9666.
Can we calculate the answer in O(N*K) (maybe dynamic programming)?
I've tried using combination.
If
N = 4, K = 3, D = 6. The number I have to find is abcd.
+) if (a = b = c = D), I choose digit for d. There are 10 ways (6660, 6661, 6662, 6663, 6664, 6665, 6666, 6667, 6668, 6669)
+) if (b = c = d = D), I choose digit for a (a > 0). There are 9 ways (1666, 2666, 3666, 4666, 5666, 6666, 7666, 8666, 9666)
But in two cases, the number 6666 is counted twice. N and K is very large, how can I count all of them?
If one is looking for a mathematical solution (vs. necessarily an algorithmic one) it's good to look at it in terms of the base cases and some formulas. They might turn out to be something you can do some kind of refactoring and get a tidy formula for. So just for the heck of it...here's a take on it that doesn't deal with the special treatment of zeros. Because that throws some wrenches in.
Let's look at a couple of base cases, and call our answer F(N,K) (not considering D, as it isn't relevant to account for; but taking it as a parameter anyway.):
when N = 0
You'll never find any length sequences of digits when there's no digit.
F(0, K) = 0 for any K.
when N = 1
Fairly obvious. If you're looking for K sequential digits in a single digit, the options are limited. Looking for more than one? No dice.
F(1, K) = 0 for any K > 1
Looking for exactly one? Okay, there's one.
F(1, 1) = 1
Sequences of zero sequential digits allowed? Then all ten digits are fine.
F(1, 0) = 10
for N > 1
when K = 0
Basically, all N-digit numbers will qualify. So the number of possibilities meeting the bar is 10^N. (e.g. when N is 3 then 000, 001, 002, ... 999 for any D)
F(N, 0) = 10^N for any N > 1
when K = 1
Possibilities meeting the condition is any number with at least one D in it. How many N-digit numbers are there which contain at least one digit D? Well, it's going to be 10^N minus all the numbers that have no instances of the digit D. 10^N - 9^N
F(N, 1) = 10^N - 9^N for any N > 1
when N < K
No way to get K sequential digits if N is less than K
F(N, K) = 0 when N < K
when N = K
Only one possible way to get K sequential digits in N digits.
F(N, K) = 1 when N = K
when N > K
Okay, we already know that N > 1 and K > 1. So this is going to be the workhorse where we hope to use subexpressions for things we've already solved.
Let's start by considering popping off the digit at the head, leaving N-1 digits on the tail. If that N-1 series could achieve a series of K digits all by itself, then adding another digit will not change anything about that. That gives us a term 10 * F(N-1, K)
But if our head digit is a D, that is special. Our cases will be:
It might be the missing key for a series that started with K-1 instances of D, creating a full range of K.
It might complete a range of K-1 instances of D, but on a case that already had a K series of adjacent D (that we thus accounted for in the above term)
It might not help at all.
So let's consider two separate categories of tail series: those that start with K-1 instances of D and those that do not. Let's say we have N=7 shown as D:DDDXYZ and with K=4. We subtract one from N and from K to get 6 and 3, and if we subtract them we get how many trailing any-digits (XYZ here) are allowed to vary. Our term for the union of (1) and (2) to add in is 10^((N-1)-(K-1)).
Now it's time for some subtraction for our double-counts. We haven't double counted any cases that didn't start with K-1 instances of D, so we keep our attention on that (DDDXYZ). If the value in the X slot is a D then it was definitely double counted. We can subtract out the term for that as 10^(((N - 1) - 1) - (K - 1)); in this case giving us all the pairings of YZ digits you can get with X as D. (100).
The last thing to get rid of are the cases where X is not a D, but in whatever that leftover after the X position there was still a K length series of D. Again we reuse our function, and subtract a term 9 * F(N - K, K, D).
Paste it all together and simplify a couple of terms you get:
F(N, K) = 10 * F(N-1,K,D) + 10^(N-K) - 10^(10,N-K-1) - 9 * F(N-K-1,K,D)
Now we have a nice functional definition suitable for Haskelling or whatever. But I'm still awkward with that, and it's easy enough to test in C++. So here it is (assuming availability of a long integer power function):
long F(int N, int K, int D) {
if (N == 0) return 0;
if (K > N) return 0;
if (K == N) return 1;
if (N == 1) {
if (K == 0) return 10;
if (K == 1) return 1;
return 0;
}
if (K == 0)
return power(10, N);
if (K == 1)
return power(10, N) - power(9, N);
return (
10 * F(N - 1, K, D)
+ power(10, N - K)
- power(10, N - K - 1)
- 9 * F(N - K - 1, K, D)
);
}
To double-check this against an exhaustive generator, here's a little C++ test program that builds the list of vectors that it scans using std::search_n. It checks the slow way against the fast way for N and K. I ran it from 0 to 9 for each:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
// http://stackoverflow.com/a/1505791/211160
long power(int x, int p) {
if (p == 0) return 1;
if (p == 1) return x;
long tmp = power(x, p/2);
if (p%2 == 0) return tmp * tmp;
else return x * tmp * tmp;
}
long F(int N, int K, int D) {
if (N == 0) return 0;
if (K > N) return 0;
if (K == N) return 1;
if (N == 1) {
if (K == 0) return 10;
if (K == 1) return 1;
return 0;
}
if (K == 0)
return power(10, N);
if (K == 1)
return power(10, N) - power(9, N);
return (
10 * F(N - 1, K, D)
+ power(10, N - K)
- power(10, N - K - 1)
- 9 * F(N - K - 1, K, D)
);
}
long FSlowCore(int N, int K, int D, vector<int> & digits) {
if (N == 0) {
if (search_n(digits.begin(), digits.end(), K, D) != end(digits)) {
return 1;
} else
return 0;
}
long total = 0;
digits.push_back(0);
for (int curDigit = 0; curDigit <= 9; curDigit++) {
total += FSlowCore(N - 1, K, D, digits);
digits.back()++;
}
digits.pop_back();
return total;
}
long FSlow(int N, int K, int D) {
vector<int> digits;
return FSlowCore(N, K, D, digits);
}
bool TestF(int N, int K, int D) {
long slow = FSlow(N, K, D);
long fast = F(N, K, D);
cout << "when N = " << N
<< " and K = " << K
<< " and D = " << D << ":\n";
cout << "Fast way gives " << fast << "\n";
cout << "Slow way gives " << slow << "\n";
cout << "\n";
return slow == fast;
}
int main() {
for (int N = 0; N < 10; N++) {
for (int K = 0; K < 10; K++) {
if (!TestF(N, K, 6)) {
exit(1);
}
}
}
}
Of course, since it counts leading zeros it will be different from the answers you got. See the test output here in this gist.
Modifying to account for the special-case zero handling is left as an exercise for the reader (as is modular arithmetic). Eliminating the zeros make it messier. Either way, this may be an avenue of attack for reducing the number of math operations even further with some transformations...perhaps.
Miquel is almost correct, but he missed a lot of cases. So, with N = 8, K = 5, and D = 6, we will need to look for those numbers that has the form:
66666xxx
y66666xx
xy66666x
xxy66666
with additional condition that y cannot be D.
So we can have our formula for this example:
66666xxx = 10^3
y66666xx = 8*10^2 // As 0 can also not be the first number
xy66666x = 9*9*10
xxy66666 = 9*10*9
So, the result is 3420.
For case N = 4, K = 3 and D = 6, we have
666x = 10
y666 = 8//Again, 0 is not counted!
So, we have 18 cases!
Note: We need to be careful that the first number cannot be 0! And we need to handle the case when D is zero too!
Update Java working code, Time complexity O(N-K)
static long cal(int n, int k, int d) {
long Mod = 1000000007;
long result = 0;
for (int i = 0; i <= n - k; i++) {//For all starting positions
if (i != 0 || d != 0) {
int left = n - k;
int upper_half = i;//Amount of digit that preceding DDD
int lower_half = n - k - i;//Amount of digit following DDD
long tmp = 1;
if (upper_half == 1) {
if (d == 0) {
tmp = 9;
} else {
tmp = 8;
}
}else if(upper_half >= 2){
//The pattern is x..yDDD...
tmp = (long) (9 * 9 * Math.pow(10, upper_half - 2));
}
tmp *= Math.pow(10, lower_half);
//System.out.println(tmp + " " + upper_half + " " + lower_half);
result += tmp;
result %= Mod;
}
}
return result;
}
Sample Tests:
N = 8, K = 5, D = 6
Output
3420
N = 4, K = 3, D = 6
Output
18
N = 4, K = 3, D = 0
Output
9

Given an integer z<=10^100, find the smallest row of Pascal's triangle that contains z [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
How can I find an algorithm to solve this problem using C++: given an integer z<=10^100, find the smallest row of Pascal's triangle that contains the number z.
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
For example if z=6 => result is on the 4th row.
Another way to describe the problem: given integer z<=10^100, find the smallest integer n: exist integer k so that C(k,n) = z.
C(k,n) is combination of n things taken k at a time without repetition
EDIT This solution needs Logarithmic time, it's O(Log z). Or maybe O( (Log z)^2 ).
Say you are looking for n,k where Binomial(n,k)==z for a given z.
Each row has its largest value in the middle, so starting from n=0 you increase the row number, n, as long as the middle value is smaller than the given number. Actually, 10^100 isn't that big, so before row 340 you find a position n0,k0=n0/2 where the value from the triangle is larger than or equal to z: Binomial(n0,k0)>=z
You walk to the left, i.e. you decrease the column number k, until eventually you find a value smaller than z. If there was a matching value in that row you would have hit it by now. k is not very large, less than 170, so this step won't be executed more often than that and does not present a performance problem.
From here you walk down, increasing n. Here you will find a steadily increasing value of Binomial[n,k]. Continue with 3 until the value gets bigger than or equal to z, then goto 2.
EDIT: This step 3 can loop for a very long time when the row number n is large, so instead of checking each n linearly you can do a binary search for n with Binomial(n,k) >= z > Binomial(n-1,k), then it only needs Log(n) time.
A Python implementation looks like this, C++ is similar but somewhat more cumbersome because you need to use an additional library for arbitrary precision integers:
# Calculate (n-k+1)* ... *n
def getnk( n, k ):
a = n
for u in range( n-k+1, n ):
a = a * u
return a
# Find n such that Binomial(n,k) >= z and Binomial(n-1,k) < z
def find_n( z, k, n0 ):
kfactorial = k
for u in range(2, k):
kfactorial *= u
xk = z * kfactorial
nk0 = getnk( n0, k )
n1=n0*2
nk1 = getnk( n1, k )
# duplicate n while the value is too small
while nk1 < xk:
nk0=nk1
n0=n1
n1*=2
nk1 = getnk( n1, k )
# do a binary search
while n1 > n0 + 1:
n2 = (n0+n1) // 2
nk2 = getnk( n2, k )
if nk2 < xk:
n0 = n2
nk0 = nk2
else:
n1 = n2
nk1 = nk2
return n1, nk1 // kfactorial
def find_pos( z ):
n=0
k=0
nk=1
# start by finding a row where the middle value is bigger than z
while nk < z:
# increase n
n = n + 1
nk = nk * n // (n-k)
if nk >= z:
break
# increase both n and k
n = n + 1
k = k + 1
nk = nk * n // k
# check all subsequent rows for a matching value
while nk != z:
if nk > z:
# decrease k
k = k - 1
nk = nk * (k+1) // (n-k)
else:
# increase n
# either linearly
# n = n + 1
# nk = nk * n // (n-k)
# or using binary search:
n, nk = find_n( z, k, n )
return n, k
z = 56476362530291763837811509925185051642180136064700011445902684545741089307844616509330834616
print( find_pos(z) )
It should print
(5864079763474581, 6)
Stirling estimation for n! can be used to find first row in triangle with binomial coefficient bigger or equal to a given x. Using this estimation we can derive lower and upper bound for
and then by observation that this is the maximum coefficient in row that expands 2n:
P( 2n, 0), P( 2n, 1), P( 2n, 2), ..., P( 2n, 2n -1), P( 2n, 2n)
we can find first row with maximum binomial coefficient bigger or equal to a given x. This is the first row in which x can be looking for, this is not possible that x can be found in the row smaller than this. Note: this may be right hint and give an answer immediately in some cases. At the moment I cannot see other way than to start a brute force search from this row.
template <class T>
T binomial_coefficient(unsigned long n, unsigned long k) {
unsigned long i;
T b;
if (0 == k || n == k) {
return 1;
}
if (k > n) {
return 0;
}
if (k > (n - k)) {
k = n - k;
}
if (1 == k) {
return n;
}
b = 1;
for (i = 1; i <= k; ++i) {
b *= (n - (k - i));
if (b < 0) return -1; /* Overflow */
b /= i;
}
return b;
}
Stirling:
double stirling_lower_bound( int n) {
double n_ = n / 2.0;
double res = pow( 2.0, 2 * n_);
res /= sqrt( n_ * M_PI);
return res * exp( ( -1.0) / ( 6 * n_));
}
double stirling_upper_bound( int n) {
double n_ = n / 2.0;
double res = pow( 2.0, 2 * n_) ;
res /= sqrt( n_ * M_PI);
return res * exp( 1.0 / ( 24 * n_));
}
int stirling_estimate( double x) {
int n = 1;
while ( stirling_lower_bound( n) <= x) {
if ( stirling_upper_bound( n) > x) return n;
++n;
}
return n;
}
usage:
long int search_coefficient( unsigned long int &n, unsigned long int x) {
unsigned long int k = n / 2;
long long middle_coefficient = binomial_coefficient<long long>( n, k);
if( middle_coefficient == x) return k;
unsigned long int right = binomial_coefficient<unsigned long>( n, ++k);
while ( x != right) {
while( x < right || x < ( right * ( n + 1) / ( k + 1))) {
right = right * ( n + 1) / ( ++k) - right;
}
if ( right == x) return k;
right = right * ( ++n) / ( ++k);
if( right > x) return -1;
}
return k;
}
/*
*
*/
int main(int argc, char** argv) {
long long x2 = 1365;
unsigned long int n = stirling_estimate( x2);
long int k = search_coefficient( n, x2);
std::cout << "row:" << n <<", column: " << k;
return 0;
}
output:
row:15, column: 11

Fast Iterative GCD

I have GCD(n, i) where i=1 is increasing in loop by 1 up to n. Is there any algorithm which calculate all GCD's faster than naive increasing and compute GCD using Euclidean algorithm?
PS I've noticed if n is prime I can assume that number from 1 to n-1 would give 1, because prime number would be co-prime to them. Any ideas for other numbers than prime?
C++ implementation, works in O(n * log log n) (assuming size of integers are O(1)):
#include <cstdio>
#include <cstring>
using namespace std;
void find_gcd(int n, int *gcd) {
// divisor[x] - any prime divisor of x
// or 0 if x == 1 or x is prime
int *divisor = new int[n + 1];
memset(divisor, 0, (n + 1) * sizeof(int));
// This is almost copypaste of sieve of Eratosthenes, but instead of
// just marking number as 'non-prime' we remeber its divisor.
// O(n * log log n)
for (int x = 2; x * x <= n; ++x) {
if (divisor[x] == 0) {
for (int y = x * x; y <= n; y += x) {
divisor[y] = x;
}
}
}
for (int x = 1; x <= n; ++x) {
if (n % x == 0) gcd[x] = x;
else if (divisor[x] == 0) gcd[x] = 1; // x is prime, and does not divide n (previous line)
else {
int a = x / divisor[x], p = divisor[x]; // x == a * p
// gcd(a * p, n) = gcd(a, n) * gcd(p, n / gcd(a, n))
// gcd(p, n / gcd(a, n)) == 1 or p
gcd[x] = gcd[a];
if ((n / gcd[a]) % p == 0) gcd[x] *= p;
}
}
}
int main() {
int n;
scanf("%d", &n);
int *gcd = new int[n + 1];
find_gcd(n, gcd);
for (int x = 1; x <= n; ++x) {
printf("%d:\t%d\n", x, gcd[x]);
}
return 0;
}
SUMMARY
The possible answers for the gcd consist of the factors of n.
You can compute these efficiently as follows.
ALGORITHM
First factorise n into a product of prime factors, i.e. n=p1^n1*p2^n2*..*pk^nk.
Then you can loop over all factors of n and for each factor of n set the contents of the GCD array at that position to the factor.
If you make sure that the factors are done in a sensible order (e.g. sorted) you should find that the array entries that are written multiple times will end up being written with the highest value (which will be the gcd).
CODE
Here is some Python code to do this for the number 1400=2^3*5^2*7:
prime_factors=[2,5,7]
prime_counts=[3,2,1]
N=1
for prime,count in zip(prime_factors,prime_counts):
N *= prime**count
GCD = [0]*(N+1)
GCD[0] = N
def go(i,n):
"""Try all counts for prime[i]"""
if i==len(prime_factors):
for x in xrange(n,N+1,n):
GCD[x]=n
return
n2=n
for c in xrange(prime_counts[i]+1):
go(i+1,n2)
n2*=prime_factors[i]
go(0,1)
print N,GCD
Binary GCD algorithm:
https://en.wikipedia.org/wiki/Binary_GCD_algorithm
is faster than Euclidean algorithm:
https://en.wikipedia.org/wiki/Euclidean_algorithm
I implemented "gcd()" in C for type "__uint128_t" (with gcc on Intel i7 Ubuntu), based on iterative Rust version:
https://en.wikipedia.org/wiki/Binary_GCD_algorithm#Iterative_version_in_Rust
Determining number of trailing 0s was done efficiently with "__builtin_ctzll()". I did benchmark 1 million loops of two biggest 128bit Fibonacci numbers (they result in maximal number of iterations) against gmplib "mpz_gcd()" and saw 10% slowdown. Utilizing the fact that u/v values only decrease, I switched to 64bit special case "_gcd()" when "<=UINT64_max" and now see speedup of 1.31 over gmplib, for details see:
https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=311893&p=1873552#p1873552
inline int ctz(__uint128_t u)
{
unsigned long long h = u;
return (h!=0) ? __builtin_ctzll( h )
: 64 + __builtin_ctzll( u>>64 );
}
unsigned long long _gcd(unsigned long long u, unsigned long long v)
{
for(;;) {
if (u > v) { unsigned long long a=u; u=v; v=a; }
v -= u;
if (v == 0) return u;
v >>= __builtin_ctzll(v);
}
}
__uint128_t gcd(__uint128_t u, __uint128_t v)
{
if (u == 0) { return v; }
else if (v == 0) { return u; }
int i = ctz(u); u >>= i;
int j = ctz(v); v >>= j;
int k = (i < j) ? i : j;
for(;;) {
if (u > v) { __uint128_t a=u; u=v; v=a; }
if (v <= UINT64_MAX) return _gcd(u, v) << k;
v -= u;
if (v == 0) return u << k;
v >>= ctz(v);
}
}

Sum of series: 1^1 + 2^2 + 3^3 + ... + n^n (mod m)

Can someone give me an idea of an efficient algorithm for large n (say 10^10) to find the sum of above series?
Mycode is getting klilled for n= 100000 and m=200000
#include<stdio.h>
int main() {
int n,m,i,j,sum,t;
scanf("%d%d",&n,&m);
sum=0;
for(i=1;i<=n;i++) {
t=1;
for(j=1;j<=i;j++)
t=((long long)t*i)%m;
sum=(sum+t)%m;
}
printf("%d\n",sum);
}
Two notes:
(a + b + c) % m
is equivalent to
(a % m + b % m + c % m) % m
and
(a * b * c) % m
is equivalent to
((a % m) * (b % m) * (c % m)) % m
As a result, you can calculate each term using a recursive function in O(log p):
int expmod(int n, int p, int m) {
if (p == 0) return 1;
int nm = n % m;
long long r = expmod(nm, p / 2, m);
r = (r * r) % m;
if (p % 2 == 0) return r;
return (r * nm) % m;
}
And sum elements using a for loop:
long long r = 0;
for (int i = 1; i <= n; ++i)
r = (r + expmod(i, i, m)) % m;
This algorithm is O(n log n).
I think you can use Euler's theorem to avoid some exponentation, as phi(200000)=80000. Chinese remainder theorem might also help as it reduces the modulo.
You may have a look at my answer to this post. The implementation there is slightly buggy, but the idea is there. The key strategy is to find x such that n^(x-1)<m and n^x>m and repeatedly reduce n^n%m to (n^x%m)^(n/x)*n^(n%x)%m. I am sure this strategy works.
I encountered similar question recently: my 'n' is 1435, 'm' is 10^10. Here is my solution (C#):
ulong n = 1435, s = 0, mod = 0;
mod = ulong.Parse(Math.Pow(10, 10).ToString());
for (ulong i = 1; i <= n;
{
ulong summand = i;
for (ulong j = 2; j <= i; j++)
{
summand *= i;
summand = summand % mod;
}
s += summand;
s = s % mod;
}
At the end 's' is equal to required number.
Are you getting killed here:
for(j=1;j<=i;j++)
t=((long long)t*i)%m;
Exponentials mod m could be implemented using the sum of squares method.
n = 10000;
m = 20000;
sqr = n;
bit = n;
sum = 0;
while(bit > 0)
{
if(bit % 2 == 1)
{
sum += sqr;
}
sqr = (sqr * sqr) % m;
bit >>= 2;
}
I can't add comment, but for the Chinese remainder theorem, see http://mathworld.wolfram.com/ChineseRemainderTheorem.html formulas (4)-(6).

Resources