Related
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).
The problem is given as:
Output the answer of (A^1+A^2+A^3+...+A^K) modulo 1,000,000,007, where 1≤ A, K ≤ 10^9, and A and K must be an integer.
I am trying to write a program to compute the above question. I have tried using the formula for geometric sequence, then applying the modulo on the answer. Since the results must be an integer as well, finding modulo inverse is not required.
Below is the code I have now, its in pascal
Var
a,k,i:longint;
power,sum: int64;
Begin
Readln(a,k);
power := 1;
For i := 1 to k do
power := ((power mod 1000000007) * a) mod 1000000007;
sum := a * (power-1) div (a-1);
Writeln(sum mod 1000000007);
End.
This task came from my school, they do not give away their test data to the students. Hence I do not know why or where my program is wrong. I only know that my program outputs the wrong answer for their test data.
If you want to do this without calculating a modular inverse, you can calculate it recursively using:
1+ A + A2 + A3 + ... + Ak
= 1 + (A + A2)(1 + A2 + (A2)2 + ... + (A2)k/2-1)
That's for even k. For odd k:
1+ A + A2 + A3 + ... + Ak
= (1 + A)(1 + A2 + (A2)2 + ... + (A2)(k-1)/2)
Since k is divided by 2 in each recursive call, the resulting algorithm has O(log k) complexity. In java:
static int modSumAtoAk(int A, int k, int mod)
{
return (modSum1ToAk(A, k, mod) + mod-1) % mod;
}
static int modSum1ToAk(int A, int k, int mod)
{
long sum;
if (k < 5) {
//k is small -- just iterate
sum = 0;
long x = 1;
for (int i=0; i<=k; ++i) {
sum = (sum+x) % mod;
x = (x*A) % mod;
}
return (int)sum;
}
//k is big
int A2 = (int)( ((long)A)*A % mod );
if ((k%2)==0) {
// k even
sum = modSum1ToAk(A2, (k/2)-1, mod);
sum = (sum + sum*A) % mod;
sum = ((sum * A) + 1) % mod;
} else {
// k odd
sum = modSum1ToAk(A2, (k-1)/2, mod);
sum = (sum + sum*A) % mod;
}
return (int)sum;
}
Note that I've been very careful to make sure that each product is done in 64 bits, and to reduce by the modulus after each one.
With a little math, the above can be converted to an iterative version that doesn't require any storage:
static int modSumAtoAk(int A, int k, int mod)
{
// first, we calculate the sum of all 1... A^k
// we'll refer to that as SUM1 in comments below
long fac=1;
long add=0;
//INVARIANT: SUM1 = add + fac*(sum 1...A^k)
//this will remain true as we change k
while (k > 0) {
//above INVARIANT is true here, too
long newmul, newadd;
if ((k%2)==0) {
//k is even. sum 1...A^k = 1+A*(sum 1...A^(k-1))
newmul = A;
newadd = 1;
k-=1;
} else {
//k is odd.
newmul = A+1L;
newadd = 0;
A = (int)(((long)A) * A % mod);
k = (k-1)/2;
}
//SUM1 = add + fac * (newadd + newmul*(sum 1...Ak))
// = add+fac*newadd + fac*newmul*(sum 1...Ak)
add = (add+fac*newadd) % mod;
fac = (fac*newmul) % mod;
//INVARIANT is restored
}
// k == 0
long sum1 = fac + add;
return (int)((sum1 + mod -1) % mod);
}
I am looking for an algorithm that expresses a given number as a sum of (up to) four squares.
Examples
120 = 82 + 62 + 42 + 22
6 = 02 + 12 + 12 + 22
20 = 42 + 22 + 02+ 02
My approach
Take the square root and repeat this repeatedly for the remainder:
while (count != 4) {
root = (int) Math.sqrt(N)
N -= root * root
count++
}
But this fails when N is 23, even though there is a solution:
32 + 32+ 22 + 12
Question
Is there any other algorithm to do that?
Is it always possible?
###Always possible?
Yes, the Lagrange's four square theorem states that:
every natural number can be represented as the sum of four integer squares.
It has been proved in several ways.
###Algorithm
There are some smarter algorithms, but I would suggest the following algorithm:
Factorise the number into prime factors. They don't have to be prime, but the smaller they are, the better: so primes are best. Then solve the task for each of these factors as below, and combine any resulting 4 squares with the previously found 4 squares with the Euler's four-square identity.
(a2 + b2 + c2 + d2)
(A2 + B2 + C2 + D2) =
(aA + bB + cC + dD)2 +
(aB − bA + cD − dC)2 +
(aC − bD − cA + dB)2 +
(aD + bC − cB − dA)2
Given a number n (one of the factors mentioned above), get the greatest square that is not greater than n, and see if n minus this square can be written as the sum of three squares using the Legendre's three-square theorem: it is possible, if and only when this number is NOT of the following form:
4a(8b+7)
If this square is not found suitable, try the next smaller one, ... until you find one. It guaranteed there will be one, and most are found within a few retries.
Try to find an actual second square term in the same way as in step 1, but now test its viability using Fermat's theorem on sums of two squares which in extension means that:
if all the prime factors of n congruent to 3 modulo 4 occur to an even exponent, then n is expressible as a sum of two squares. The converse also holds.
If this square is not found suitable, try the next smaller one, ... until you find one. It's guaranteed there will be one.
Now we have a remainder after subtracting two squares. Try subtracting a third square until that yields another square, which means we have a solution. This step can be improved by first factoring out the largest square divisor. Then when the two square terms are identified, each can then be multiplied again by the square root of that square divisor.
This is roughly the idea. For finding prime factors there are several solutions. Below I will just use the Sieve of Eratosthenes.
This is JavaScript code, so you can run it immediately -- it will produce a random number as input and display it as the sum of four squares:
function divisor(n, factor) {
var divisor = 1;
while (n % factor == 0) {
n = n / factor;
divisor = divisor * factor;
}
return divisor;
}
function getPrimesUntil(n) {
// Prime sieve algorithm
var range = Math.floor(Math.sqrt(n)) + 1;
var isPrime = Array(n).fill(1);
var primes = [2];
for (var m = 3; m < range; m += 2) {
if (isPrime[m]) {
primes.push(m);
for (var k = m * m; k <= n; k += m) {
isPrime[k] = 0;
}
}
}
for (var m = range + 1 - (range % 2); m <= n; m += 2) {
if (isPrime[m]) primes.push(m);
}
return {
primes: primes,
factorize: function (n) {
var p, count, primeFactors;
// Trial division algorithm
if (n < 2) return [];
primeFactors = [];
for (p of this.primes) {
count = 0;
while (n % p == 0) {
count++;
n /= p;
}
if (count) primeFactors.push({value: p, count: count});
}
if (n > 1) {
primeFactors.push({value: n, count: 1});
}
return primeFactors;
}
}
}
function squareTerms4(n) {
var n1, n2, n3, n4, sq, sq1, sq2, sq3, sq4, primes, factors, f, f3, factors3, ok,
res1, res2, res3, res4;
primes = getPrimesUntil(n);
factors = primes.factorize(n);
res1 = n > 0 ? 1 : 0;
res2 = res3 = res4 = 0;
for (f of factors) { // For each of the factors:
n1 = f.value;
// 1. Find a suitable first square
for (sq1 = Math.floor(Math.sqrt(n1)); sq1>0; sq1--) {
n2 = n1 - sq1*sq1;
// A number can be written as a sum of three squares
// <==> it is NOT of the form 4^a(8b+7)
if ( (n2 / divisor(n2, 4)) % 8 !== 7 ) break; // found a possibility
}
// 2. Find a suitable second square
for (sq2 = Math.floor(Math.sqrt(n2)); sq2>0; sq2--) {
n3 = n2 - sq2*sq2;
// A number can be written as a sum of two squares
// <==> all its prime factors of the form 4a+3 have an even exponent
factors3 = primes.factorize(n3);
ok = true;
for (f3 of factors3) {
ok = (f3.value % 4 != 3) || (f3.count % 2 == 0);
if (!ok) break;
}
if (ok) break;
}
// To save time: extract the largest square divisor from the previous factorisation:
sq = 1;
for (f3 of factors3) {
sq *= Math.pow(f3.value, (f3.count - f3.count % 2) / 2);
f3.count = f3.count % 2;
}
n3 /= sq*sq;
// 3. Find a suitable third square
sq4 = 0;
// b. Find square for the remaining value:
for (sq3 = Math.floor(Math.sqrt(n3)); sq3>0; sq3--) {
n4 = n3 - sq3*sq3;
// See if this yields a sum of two squares:
sq4 = Math.floor(Math.sqrt(n4));
if (n4 == sq4*sq4) break; // YES!
}
// Incorporate the square divisor back into the step-3 result:
sq3 *= sq;
sq4 *= sq;
// 4. Merge this quadruple of squares with any previous
// quadruple we had, using the Euler square identity:
while (f.count--) {
[res1, res2, res3, res4] = [
Math.abs(res1*sq1 + res2*sq2 + res3*sq3 + res4*sq4),
Math.abs(res1*sq2 - res2*sq1 + res3*sq4 - res4*sq3),
Math.abs(res1*sq3 - res2*sq4 - res3*sq1 + res4*sq2),
Math.abs(res1*sq4 + res2*sq3 - res3*sq2 - res4*sq1)
];
}
}
// Return the 4 squares in descending order (for convenience):
return [res1, res2, res3, res4].sort( (a,b) => b-a );
}
// Produce the result for some random input number
var n = Math.floor(Math.random() * 1000000);
var solution = squareTerms4(n);
// Perform the sum of squares to see it is correct:
var check = solution.reduce( (a,b) => a+b*b, 0 );
if (check !== n) throw "FAILURE: difference " + n + " - " + check;
// Print the result
console.log(n + ' = ' + solution.map( x => x+'²' ).join(' + '));
The article by by Michael Barr on the subject probably represents a more time-efficient method, but the text is more intended as a proof than an algorithm. However, if you need more time-efficiency you could consider that, together with a more efficient factorisation algorithm.
It's always possible -- it's a theorem in number theory called "Lagrange's four square theorem."
To solve it efficiently: the paper Randomized algorithms in number theory (Rabin, Shallit) gives a method that runs in expected O((log n)^2) time.
There is interesting discussion about the implementation here: https://math.stackexchange.com/questions/483101/rabin-and-shallit-algorithm
Found via Wikipedia:Langrange's four square theorem.
Here is solution , Simple 4 loops
max = square_root(N)
for(int i=0;i<=max;i++)
for(int j=0;j<=max;j++)
for(int k=0;k<=max;k++)
for(int l=0;l<=max;l++)
if(i*i+j*j+k*k+l*l==N){
found
break;
}
So you can test for any numbers. You can use break condition after two loops if sum exceeds then break it.
const fourSquares = (n) => {
const result = [];
for (let i = 0; i <= n; i++) {
for (let j = 0; j <= n; j++) {
for (let k = 0; k <= n; k++) {
for (let l = 0; l <= n; l++) {
if (i * i + j * j + k * k + l * l === n) {
result.push(i, j, k, l);
return result;
}
}
}
}
}
return result;
}
It's running too long
const fourSquares = (n) => {
const result = [];
for (let i = 0; i <= n; i++) {
for (let j = 0; j <= (n - i * i); j++) {
for (let k = 0; k <= (n - i * i - j * j); k++) {
for (let l = 0; l <= (n - i * i - j * j - k * k); l++) {
if (i * i + j * j + k * k + l * l === n) {
result.push(i, j, k, l);
return result;
}
}
}
}
}
return result;
}
const fourSquares = (n) => {
const result = [];
for (let i = 0; i * i <= n; i++) {
for (let j = 0; j * j <= n; j++) {
for (let k = 0; k * k <= n; k++) {
for (let l = 0; l * l <= n; l++) {
if (i * i + j * j + k * k + l * l === n) {
result.push(i, j, k, l);
return result;
}
}
}
}
}
return result;
}
const fourSquares = (n) => {
let a = Math.sqrt(n);
let b = Math.sqrt(n - a * a);
let c = Math.sqrt(n - a * a - b * b);
let d = Math.sqrt(n - a * a - b * b - c * c);
if (n === a * a + b * b + c * c + d * d) {
return [a, b, c, d];
}
}
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
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).