Problem
Given an array A = a0,a1,...an, with size up to N ≤ 10^5, and 0 ≤ ai ≤ 10^9.
And a number 0 < M ≤ 10^9.
The task is to find the maximum ∑(k=i, j) ak % M = (ai + ai+1 + a(i+2) + ⋯ + a(j−1) + a(j)) % M, and how many different range(i,j) get that sum.
The complexity has to be less than O(N^2), the latter is too slow.
Example
N = 3, M = 5
A = {2, 4, 3}
The Maximum Sum mod M is 4 and there are 2 ranges, which are a0 to a2 and a1
My attempt
Let's define s[j] = (a0 + a1 + ... + aj) % M so if you want the best sum that ends in j you have to choose an s[i] i < j that s[i] is the smallest sum higher than you.
Because if s[i] > s[j]; s[i] = M - K; K < M - s[j] then the result sum range will be (s[j]-s[i]+M) % M = (s[j] + K) % M and because K < M - s[j] it will increase the result mod M, and as s[j] gets closer to s[j] it will increase the result mod M.
The idea is my attemp, first you have to have to calculate all the sums that starts from 0 and end in a index i, then you can search the smaller value grater than you fast by searching the value with a binary search that the map already have (lower_bound), and count how many time you could do sum with the value that you found. You have to keep the sum somewhere to count how many time you could do it.
#include <iostream>
#include <map>
#define optimizar_io ios_base::sync_with_stdio(false);cin.tie(NULL);
using namespace std;
const int LN = 1e5;
long long N, M, num[LN];
map < long long, int > sum;
int main() {
optimizar_io
cin >> N >> M;
sum[0]++;
long long cont = 0, tmax = 0, res = 1, val;
map < long long, int > :: iterator best;
for (int i = 0; i < N; i++)
{
cin >> num[i];
cont = (cont + num[i]) % M;
if (tmax == cont)
res += sum[0];
if (tmax < cont)
tmax = cont, res = sum[0];
best = sum.lower_bound(cont + 1);
if (best != sum.end())
{
val = cont - (*best).first + M;
if (tmax == val)
res += (*best).second;
if (tmax < val)
tmax = val, res = (*best).second;
}
sum[cont]++;
}
cout << tmax << " " << res;
return 0;
}
Related
Question is as follows :
Given two numbers n and k. For each number in the interval [1, n], your task is to calculate its largest divisor that is not divisible by k. Print the sum of all these divisors.
Note: k is always a prime number.
t=3*10^5,1<=n<=10^9, 2<=k<=10^9
My approach toward the question:
for every i in range 1 to n, the required divisors is i itself,only when that i is not a multiple of k.
If that i is multiple of k, then we have to find the greatest divisor of a number and match with k. If it does not match, then this divisor is my answer. otherwise, 2nd largest divisor is my answer.
for example,take n=10 and k=2, required divisors for every i in range 1 to 10 is 1, 1, 3, 1, 5, 3, 7, 1, 9, 5. sum of these divisors are 36. So ans=36.
My code,which works for a few test cases and failed for some.
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
ll div2(ll n, ll k) {
if (n % k != 0 || n == 1) {
return n;
}
else {
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
ll aa = n / i;
if (aa % k != 0) {
return aa;
}
}
}
}
return 1;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while (t--) {
ll n, k;
cin >> n >> k;
ll sum = 0, pp;
for (pp = 1; pp <= n; pp++) {
//cout << div2(pp, k);
sum = sum + div2(pp, k);
}
cout << sum << '\n';
}
}
Can someone help me where I am doing wrong or suggest me some faster logic to do this question as some of my test cases is showing TIME LIMIT EXCEED
after looking every possible explanation , i modify my code as follows:
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while (t--) {
ll n, i;
ll k, sum;
cin >> n >> k;
sum = (n * (n + 1)) / 2;
for (i = k; i <= n; i = i + k) {
ll dmax = i / k;
while (dmax % k == 0) {
dmax = dmax / k;
}
sum = (sum - i) + dmax;
}
cout << sum << '\n';
}
}
But still it is giving TIME LIMIT EXCEED for 3 test cases. Someone please help.
Like others already said, look at the constraints: t=3*10^5,1<=n<=10^9, 2<=k<=10^9.
If your test has a complexity O(n), which computing the sum via a loop has, you'll end up doing a t * n ~ 10^14. That's too much.
This challenge is a math one. You'll need to use two facts:
as you already saw, if i = j * k^s with j%k != 0, the largest divisor is j;
sum_{i=1}^t i = (t * (t+1)) / 2
We start with
S = sum(range(1, n)) = n * (n+1) / 2
then for all number of the form k * x we added too much, let's correct:
S = S - sum(k*x for x in range(1, n/k)) + sum(x for x in range(1, n/k))
= S - (k - 1) * (n/k) * (n/k + 1) / 2
continue for number of the form k^2 * x ... then k^p * x until the sum is empty...
Ok, people start writing code, so here's a small Python function:
def so61867604(n, k):
S = (n * (n+1)) // 2
k_pow = k
while k_pow <= n:
up = n // k_pow
S = S - (k - 1) * (up * (up + 1)) // 2
k_pow *= k
return S
and in action here https://repl.it/repls/OlivedrabKeyProjections
In itself this is more of a mathematical problem:
If cur = [1..n], as you have already noticed, the largest divisor = dmax = cur is, if cur % k != 0, otherwise dmax must be < cur. From k we know that it is at most divisible into other prime numbers... Since we want to make sure that dmax is not divisible by k we can do this with a while loop... whereby this is certainly also more elegantly possible (since dmax must be a prime number again due to the prime factorization).
So this should look like this (without guarantee just typed down - maybe I missed something in my thinking):
#include <iostream>
int main() {
unsigned long long n = 10;
unsigned long long k = 2;
for (auto cur_n = decltype(n){1}; cur_n <= n; cur_n++)
{
if (cur_n % k != 0) {
std::cout << "Largest divisor for " << cur_n << ": " << cur_n << " (SELF)" << std::endl;
} else {
unsigned long long dmax= cur_n/k;
while (dmax%k == 0)
dmax= dmax/k;
std::cout << "Largest divisor for " << cur_n << ": " << dmax<< std::endl;
}
}
}
I wonder if something like this is what One Lyner means.
(Note, this code has two errors in it, which are described in the comments, as well as can be elucidated by One Lyner's new code.)
C++ code:
#include <vector>
#include <iostream>
using namespace std;
#define ll long long int
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while (t--) {
ll n;
ll k, _k, result;
vector<ll> powers;
cin >> n >> k;
result = n * (n + 1) / 2;
_k = k;
while (_k <= n) {
powers.push_back(_k);
_k = _k * k;
}
for (ll p : powers) {
ll num_js = n / p;
result -= num_js * (num_js + 1) / 2 * (p - 1);
int i = 0;
while (p * powers[i] <= n) {
result += powers[i] * (p - 1);
i = i + 1;
}
}
cout << result << '\n';
}
}
If I have multiplication table 3x4
1 2 3 4
2 4 6 8
3 6 9 12
and put all these numbers in the order:
1 2 2 3 3 4 4 6 6 8 9 12
What number at the K position?
For example, if K = 5, then this is number 3.
N and M in the range 1 to 500 000. K is always less then N * M.
I've tried to use binary-search like in this(If an NxM multiplication table is put in order, what is number in the middle?) solution, but there some mistake if desired value not in the middle of sequence.
long findK(long n, long m, long k)
{
long min = 1;
long max = n * m;
long ans = 0;
long prev_sum = 0;
while (min <= max) {
ans = (min + max) / 2;
long sum = 0;
for (int i = 1; i <= m; i++)
{
sum += std::min(ans / i, n);
}
if (prev_sum + 1 == sum) break;
sum--;
if (sum < k) min = ans - 1;
else if (sum > k) max = ans + 1;
else break;
prev_sum = sum;
}
long sum = 0;
for (int i = 1; i <= m; i++)
sum += std::min((ans - 1) / i, n);
if (sum == k) return ans - 1;
else return ans;
}
For example, when N = 1000, M = 1000, K = 876543; expected value is 546970, but returned 546972.
I believe that the breakthrough will lie with counting the quantity of factorizations of each integer up to the desired point. For each integer prod, you need to count how many simple factorizations i*j there are with i <= m, j <= n. See the divisor functions.
You need to iterate prod until you reach the desired point, midpt = N*M / 2. Cumulatively subtract σ0(prod) from midpt until you reach 0. Note that once prod passes min(i, j), you need to start cropping the divisor count, due to running off the edge of the multiplication table.
Is that enough to get you started?
Code of third method from this(https://leetcode.com/articles/kth-smallest-number-in-multiplication-table/#) site solve the problem.
bool enough(int x, int m, int n, int k) {
int count = 0;
for (int i = 1; i <= m; i++) {
count += std::min(x / i, n);
}
return count >= k;
}
int findK(int m, int n, int k) {
int lo = 1, hi = m * n;
while (lo < hi) {
int mi = lo + (hi - lo) / 2;
if (!enough(mi, m, n, k)) lo = mi + 1;
else hi = mi;
}
return lo;
}
A Magic Fraction for N is one that has the following properties:
It is a proper fraction (The value is < 1)
It cannot be reduced further (The GCD of the numerator and the denominator is 1)
The product of the numerator and the denominator is factorial of N. i.e. if a/b is the fraction, then a*b = N!
Examples of Magic Fractions are:
1/2 [ gcd(1,2) = 1 and 1*2=2! ]
2/3 [ gcd(2,3) = 1 and 2*3=3! ]
3/8 [ gcd(3,8) = 1 and 3*8=4! ]
2/12 for example, is not a magic fraction, as even though 2*12=4!, gcd(2,12) != 1
And Magic fractions for number 3 are: 2/3 and 1/6 (since both of them satisfy the above criteria, are of the form a/b where a*b = 3!)
Now given a number N, you need to print the total number of magic fractions that exist, for all numbers between 1 and N (include magic fractions for N, too).
Can anybody tell me what is modPow function doing?
Refer the link to see the question, that will give an idea why this code.
using namespace std;
#define ll long long int
#define S(n) scanf("%lld", &n)
ll MOD = 1e18 + 7;
ll modPow(ll a, ll b)
{
ll res = 1;
a %= MOD;
for (; b; b >>= 1) {
if (b & 1)
res = res * a % MOD;
a = a * a % MOD;
}
return res;
}
int main()
{
ll i, j;
ll va = 1;
ll sum = 0;
ll prime[1000] = { 0 };
for (i = 2; i <= 500; i++) {
if (prime[i] == 0)
for (j = 2 * i; j <= 500; j += i)
prime[j] = 1;
}
ll val[600] = { 0 };
val[1] = 0;
val[2] = 1;
ll co = 0;
for (i = 3; i <= 500; i++) {
if (prime[i] == 0) {
co++;
}
ll t1 = modPow(2, co);
val[i] = t1 + val[i - 1];
val[i] %= MOD;
// cout << i << " " << val[i] << "\n";
}
ll n;
S(n);
cout << val[n] << "\n";
}
I tried to create a function which takes two variables n and k.
The function returns the number of positive integers that have prime factors all less than or equal to k. The number of positive integers is limited by n which is the largest positive integer.
For example, if k = 4 and n = 10; the positive integers which have all prime factors less than or equal to 4 are 1, 2, 3, 4, 6, 8, 9, 12...(1 is always part for some reason even though its not prime) but since n is 10, 12 and higher numbers are ignored.
So the function will return 7. The code I wrote works for smaller values of n while it just keeps on running for larger values.
How can I optimize this code? Should I start from scratch and come up with a better algorithm?
int generalisedHammingNumbers(int n, int k)
{
vector<int>store;
vector<int>each_prime = {};
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= i; ++j)
{
if (i%j == 0 && is_prime(j))
{
each_prime.push_back(j); //temporary vector of prime factors for each integer(i)
}
}
for (int m = 0; m<each_prime.size(); ++m)
{
while(each_prime[m] <= k && m<each_prime.size()-1) //search for prime factor greater than k
{
++m;
}
if (each_prime[m] > k); //do nothing for prime factor greater than k
else store.push_back(i); //if no prime factor greater than k, i is valid, store i
}
each_prime = {};
}
return (store.size()+1);
}
bool is_prime(int x)
{
vector<int>test;
if (x != 1)
{
for (int i = 2; i < x; ++i)
{
if (x%i == 0)test.push_back(i);
}
if (test.size() == 0)return true;
else return false;
}
return false;
}
int main()
{
long n;
int k;
cin >> n >> k;
long result = generalisedHammingNumbers(n, k);
cout << result << endl;
}
Should I start from scratch and come up with a better algorithm?
Yes... I think so.
This seems to me a work for the Sieve of Eratosthenes.
So I propose to
1) create a std::vector<bool> to detect, through Eratosthenes, the primes to n
2) remove primes starting from k+1, and their multiples, from the pool of your numbers (another std::vector<bool>)
3) count the true remained values in the pool vector
The following is a full working example
#include <vector>
#include <iostream>
#include <algorithm>
std::size_t foo (std::size_t n, std::size_t k)
{
std::vector<bool> primes(n+1U, true);
std::vector<bool> pool(n+1U, true);
std::size_t const sqrtOfN = std::sqrt(n);
// first remove the not primes from primes list (Sieve of Eratosthenes)
for ( auto i = 2U ; i <= sqrtOfN ; ++i )
if ( primes[i] )
for ( auto j = i << 1 ; j <= n ; j += i )
primes[j] = false;
// then remove from pool primes, bigger than k, and multiples
for ( auto i = k+1U ; i <= n ; ++i )
if ( primes[i] )
for ( auto j = i ; j <= n ; j += i )
pool[j] = false;
// last count the true value in pool (excluding the zero)
return std::count(pool.begin()+1U, pool.end(), true);
}
int main ()
{
std::cout << foo(10U, 4U) << std::endl;
}
Generate the primes using a sieve of Erastothenes, and then use a modified coin-change algorithm to find numbers which are products of only those primes. In fact, one can do both simultaneously like this (in Python, but is easily convertible to C++):
def limited_prime_factors(n, k):
ps = [False] * (k+1)
r = [True] * 2 + [False] * n
for p in xrange(2, k+1):
if ps[p]: continue
for i in xrange(p, k+1, p):
ps[i] = True
for i in xrange(p, n+1, p):
r[i] = r[i//p]
return [i for i, b in enumerate(r) if b]
print limited_prime_factors(100, 3)
The output is:
[0, 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 54, 64, 72, 81, 96]
Here, each time we find a prime p, we strike out all multiples of p in the ps array (as a standard Sieve of Erastothenes), and then in the r array, mark all multiples of any number that's a multiple of p whether their prime factors are all less than or equal to p.
It runs in O(n) space and O(n log log k) time, assuming n>k.
A simpler O(n log k) solution tests if all the factors of a number are less than or equal to k:
def limited_prime_factors(n, k):
r = [True] * 2 + [False] * n
for p in xrange(2, k+1):
for i in xrange(p, n+1, p):
r[i] = r[i//p]
return [i for i, b in enumerate(r) if b]
Here's an Eulerian version in Python (seems about 1.5 times faster than Paul Hankin's). We generate only the numbers themselves by multiplying a list by each prime and its powers in turn.
import time
start = time.time()
n = 1000000
k = 100
total = 1
a = [None for i in range(0, n+1)]
s = []
p = 1
while (p < k):
p = p + 1
if a[p] is None:
#print("\n\nPrime: " + str(p))
a[p] = True
total = total + 1
s.append(p)
limit = n / p
new_s = []
for i in s:
j = i
while j <= limit:
new_s.append(j)
#print j*p
a[j * p] = True
total = total + 1
j = j * p
s = new_s
print("\n\nGilad's answer: " + str(total))
end = time.time()
print(end - start)
# Paul Hankin's solution
def limited_prime_factors(n, k):
ps = [False] * (k+1)
r = [True] * 2 + [False] * n
for p in xrange(2, k+1):
if ps[p]: continue
for i in xrange(p, k+1, p):
ps[i] = True
for i in xrange(p, n+1, p):
r[i] = r[i//p]
return len([i for i, b in enumerate(r) if b]) - 1
start = time.time()
print "\nPaul's answer:" + str(limited_prime_factors(1000000, 100))
end = time.time()
print(end - start)
I'm trying to solve a coding challenge on hacker rank which requires one to calculate binomial coefficients mod a prime, i.e.
nchoosek(n, k, p)
I'm using the code from this answer that works for the first three sets of inputs but begins failing on the 4th. I stepped through it in the debugger and determined that the issue arises when:
n % p == 0 || k % p == 0
I just need to know how to modify my current solution to handle the specific cases where n % p == 0 or k % p == 0. None of the answers I've found on stack exchange seem to address this specific case. Here's my code:
#include <iostream>
#include <fstream>
long long FactorialExponent(long long n, long long p)
{
long long ex = 0;
do
{
n /= p;
ex += n;
}while(n > 0);
return ex;
}
unsigned long long ModularMultiply(unsigned long long a, unsigned long long b, unsigned long p) {
unsigned long long a1 = (a >> 21), a2 = a & ((1ull << 21) - 1);
unsigned long long temp = (a1 * b) % p; // doesn't overflow under the assumptions
temp = (temp << 21) % p; // this neither
temp += (a2 * b) % p; // nor this
return temp % p;
}
unsigned long long ModularInverse(unsigned long long k, unsigned long m) {
if (m == 0) return (k == 1 || k == -1) ? k : 0;
if (m < 0) m = -m;
k %= m;
if (k < 0) k += m;
int neg = 1;
unsigned long long p1 = 1, p2 = 0, k1 = k, m1 = m, q, r, temp;
while(k1 > 0) {
q = m1 / k1;
r = m1 % k1;
temp = q*p1 + p2;
p2 = p1;
p1 = temp;
m1 = k1;
k1 = r;
neg = !neg;
}
return neg ? m - p2 : p2;
}
// Preconditions: 0 <= k <= min(n,p-1); p > 1 prime
unsigned long long ChooseModTwo(unsigned long long n, unsigned long long k, unsigned long p)
{
// reduce n modulo p
n %= p;
// Trivial checks
if (n < k) {
return 0;
}
if (k == 0 || k == n) {
return 1;
}
// Now 0 < k < n, save a bit of work if k > n/2
if (k > n/2) {
k = n-k;
}
// calculate numerator and denominator modulo p
unsigned long long num = n, den = 1;
for(n = n-1; k > 1; --n, --k)
{
num = ModularMultiply(num, n, p);
den = ModularMultiply(den, k, p);
}
den = ModularInverse(den,p);
return ModularMultiply(num, den, p);
}
// Preconditions: 0 <= k <= n; p > 1 prime
long long ChooseModOne(long long n, long long k, const unsigned long p)
{
// For small k, no recursion is necessary
if (k < p) return ChooseModTwo(n,k,p);
unsigned long long q_n, r_n, q_k, r_k, choose;
q_n = n / p;
r_n = n % p;
q_k = k / p;
r_k = k % p;
choose = ChooseModTwo(r_n, r_k, p);
// If the exponent of p in choose(n,k) isn't determined to be 0
// before the calculation gets serious, short-cut here:
// if (choose == 0) return 0;
return ModularMultiply(choose, ChooseModOne(q_n, q_k, p), p);
}
unsigned long long ModularBinomialCoefficient(unsigned long long n, unsigned long long k, const unsigned long p)
{
// We deal with the trivial cases first
if (k < 0 || n < k) return 0;
if (k == 0 || k == n) return 1;
// Now check whether choose(n,k) is divisible by p
if (FactorialExponent(n, p) > FactorialExponent(k, p) + FactorialExponent(n - k, p)) return 0;
// If it's not divisible, do the generic work
return ChooseModOne(n, k, p);
}
int main() {
//std::ifstream fin ("input03.txt");
std::ifstream fin ("test.in");
int kMod = 1000003;
int T;
fin >> T;
int N = T;
//std::cin >> T;
unsigned long long n, k;
unsigned long long a, b;
int result[N];
int index = 0;
while (T--) {
fin >> n >> k;
a = ModularBinomialCoefficient(n - 3, k, kMod);
b = ModularBinomialCoefficient(n + k, n - 1, kMod);
// (1 / (n + k) * nCk(n - 3, k) * nCk(n + k, n - 1)) % 1000003
unsigned long long x = ModularMultiply(a, b, kMod);
unsigned long long y = ModularMultiply(x, ModularInverse((n + k), kMod), kMod);
result[index] = y;
index++;
}
for(int i = 0; i < N; i++) {
std::cout << result[i] << "\n";
}
return 0;
}
Input:
6
90 13
65434244 16341234
23424244 12341234
424175 341198
7452123 23472
56000168 16000048
Output:
815483
715724
92308
903465
241972
0 <-- Incorrect, should be: 803478
Constraints:
4 <= N <= 10^9
1 <= K <= N
You can use Lucas' theorem to reduce the problem to ceil(log_P(N)) subproblems with k, n < p: Write n = n_m * p^m + ... + n_0 and k = k_m * p^m + ... + k_0 in base p (n_i, k_i < p are the digits), then we have
C(n,k) = PROD(i = 0 to m, C(n_i, k_i)) (mod p)
The subproblems are easy to solve, because every factor of k! has an inverse modulo p. You get an algorithm with runtime complexity O(p log(n)), which is better than that of Ivaylo's code in case of p << n, if I understand it correctly.
int powmod(int x, int e, int p) {
if (e == 0) return 1;
if (e & 1) return (long long)x * powmod(x, e - 1, p) % p;
long long rt = powmod(x, e / 2, p);
return rt * rt % p;
}
int binom_coeff_mod_prime(int n, int k, int p) {
long long res = 1;
while (n || k) {
int N = n % p, K = k % p;
for (int i = N - K + 1; i <= N; ++i)
res = res * i % p;
for (int i = 1; i <= K; ++i)
res = res * powmod(i, p - 2, p) % p;
n /= p;
k /= p;
}
return res;
}
I suggest you use factorization to compute the number of combinations without division. I've got code for doing so here, originally inspired by Fast computation of multi-category number of combinations (I still would like to post a proper answer to that, if some kind souls would reopen it).
My code stores the result as a table of factors, doing the modular multiplication to expand the result should be quite straightforward.
Probably not practical for n in the range of 10**9, though, since the sieve will be quite massive and take a while to construct.