Problem Link - https://cses.fi/problemset/task/1712
input -
1
7
8
10
Expected Output - 928742408
My output - 989820350
point that is confusing me - Out of 100s of inputs, in only 1 or 2 test cases my code is providing wrong output, if the code is wrong shouldn't it give wrong output for everything?
My code -
#include <iostream>
#include <algorithm>
typedef unsigned long long ull;
constexpr auto N = 1000000007;
using namespace std;
ull binpow(ull base, ull pwr) {
base %= N;
ull res = 1;
while (pwr > 0) {
if (pwr & 1)
res = res * base % N;
base = base * base % N;
pwr >>= 1;
}
return res;
}
ull meth(ull a, ull b, ull c) {
if (a == 0 && (b == 0 || c == 0))
return 1;
if (b == 0 && c == 0)
return 1;
if (c == 0)
return a;
ull pwr = binpow(b, c);
ull result = binpow(a, pwr);
return result;
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
ull a, b, c, n;
cin >> n;
for (ull i = 0; i < n; i++) {
cin >> a >> b >> c;
cout << meth(a, b, c) << "\n";
}
return 0;
}
`
Your solution is based on an incorrect mathematical assumption. If you want to compute abc mod m you can't reduce the exponent bc mod 109 + 7. In other words, abc mod m != abc mod m mod m. Instead, you can reduce it mod 109 + 6 which works because of Fermat's little theorem. Therefore, you need to compute your exponent bc under a different modulus.
For reference
Change
ull pwr = binpow(b, c);
To a pwr = bc calculation.
810 --> 1,073,741,824
71,073,741,824 mod 100000007 --> 928742408
if the code is wrong shouldn't it give wrong output for everything?
Likely the other bc were always < 100000007
Related
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'm trying to find the sum of all divisors of c in a give range a, b a <= b.
I've tried to loop from a to b and sum all divisors of c, but this seems inefficient, because the absolute difference between a and b can be 10^9.
Is there a way that reduces the time complexity of this approach?
int a, b, c;
cin >> a >> b >> c;
long long sum = 0;
for (int i = a; i <= b; i++) {
if (i % c == 0) {
ans += i;
}
}
cout << sum << endl;
Note: the question is unclear whether we need to sum divisors (in the description) or divisible integers (in the code sample). The answer sums up divisible items.
This is simple.
Find from, the smallest value such that from % c == 0 && from >= a
Find to, the largest value such that to % c == 0 && to <= b
.
int n = (to - from) / c + 1;
return n * (to + from) / 2;
Return to - from + c. Take care of boundary conditions when to could overflow your type and from can underflow.
To find from do something like:
if (c < 0) c *= -1; // works unless c == MIN_INT
if (a % c == 0)
from = a;
else if (a >= 0)
from = (a / c * c) + c
else
from = a / c * c;
Similarly for to, but accounting for the fact that we need to round down, and not up.
Also, need to handle the case of a > b separately.
EDIT
Here is the complete code with no loops, recursion, or containers. It runs in O(1):
int a, b, c;
std::cin >> a >> b >> c;
if (!std::cin) {
std::cout << "input error\n";
return 0;
}
if (c < 0) c*= -1;
const int from = [a,c] {
// no rounding needed
if (a % c == 0) return a;
// division rounds down to zero
if (a > 0) return (1 + a / c) * c;
// division rounds up to zero
return a / c * c;
}();
const int to = [b,c] {
// no rounding needed
if (b % c == 0) return b;
// division rounds down to zero
if (b > 0) return (b / c) * c;
// division rounds up to zero
return (b / c - 1) * c;
}();
int64_t sum = 0;
if (from <= to)
{
const int n = (to - from) / c + 1;
sum = n * (to + from) / 2;
}
std::cout << sum << '\n';
Identify all the prime numbers that are divisors of c first. That will leave you with a list of numbers [w,x,y,z…]. Then keep a hash table set of all multiples of integers in this list that are also divisors.
int a, b, c;
cin >> a >> b >> c;
long long sum = 0;
std::vector<int> all_prime_factors = // Get all prime factors of c
std::unordered_set<int> factorSet;
for (int primefactor : all_prime_factors)
{
int factor = primefactor;
while (factor <= b)
{
if (factor % c == 0)
factorSet.insert(factor);
factor += primefactor;
}
}
for (int x : factorSet)
{
sum += x;
}
cout << sum << endl;
It's the first time that I use the gmp library, so I'm really lost, I've found a code implementing the "miller rabin primality test" in c++ but I wanted to be able to apply it to integers with arbitrary precision so I installed the GMP library.
The problem is, I've got no idea of how GMP library actually works (I've read trough a few pages of the manual but I understand very little about it also since I haven't even studied object oriented programming), I want to adapt the primality test to be able to input integers 'num' of about 1000-2000 digits, here's the code:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <gmpxx.h>
#include <gmp.h>
#define ll long long
using namespace std;
/*
* calculates (a * b) % c taking into account that a * b might overflow
*/
ll mulmod(ll a, ll b, ll mod)
{
ll x = 0,y = a % mod;
while (b > 0)
{
if (b % 2 == 1)
{
x = (x + y) % mod;
}
y = (y * 2) % mod;
b /= 2;
}
return x % mod;
}
/*
* modular exponentiation
*/
ll modulo(ll base, ll exponent, ll mod)
{
ll x = 1;
ll y = base;
while (exponent > 0)
{
if (exponent % 2 == 1)
x = (x * y) % mod;
y = (y * y) % mod;
exponent = exponent / 2;
}
return x % mod;
}
/*
* Miller-Rabin primality test, iteration signifies the accuracy
*/
bool Miller(ll p,int iteration)
{
if (p < 2)
{
return false;
}
if (p != 2 && p % 2==0)
{
return false;
}
ll s = p - 1;
while (s % 2 == 0)
{
s /= 2;
}
for (int i = 0; i < iteration; i++)
{
ll a = rand() % (p - 1) + 1, temp = s;
ll mod = modulo(a, temp, p);
while (temp != p - 1 && mod != 1 && mod != p - 1)
{
mod = mulmod(mod, mod, p);
temp *= 2;
}
if (mod != p - 1 && temp % 2 == 0)
{
return false;
}
}
return true;
}
//Main
int main()
{
int w=0;
int iteration = 5;
mpz_t num;
cout<<"Enter integer to loop: ";
cin>>num;
if (num % 2 == 0)
num=num+1;
while (w==0) {
if (Miller(num, iteration)) {
cout<<num<<" is prime"<<endl;
w=1;
}
else
num=num+2;
}
system ("PAUSE");
return 0;
}
(If I define num to be 'long long' the program works just fine, but I have no idea how I should adapt the whole thing to "match" num being defined as 'mpz_t' instead, also I didn't mention it but the program basically takes an initial integer value and loops it by adding 2 if the integer is composite until it becomes a prime number)
Currently the following problem is taking 3.008** seconds to execute for some testcase provided on hackerearth.com where allowed time is 3.0 seconds so i get time limit error. Please help to reduce execution time.
Problem:
Alice has just learnt multiplying two integers. He wants to multiply two integers X and Y to form a number Z.To make the problem interesting he will choose X in the range [1,M] and Y in the range [1,N].Help him to find the number of ways in which he can do this.
Input
First line of the input is the number of test cases T. It is followed by T lines. Each line has three space separated integers, the numbers Z, M and N.
Output
For each test case output a single integer, the number of ways.
Constraints
1 <= T <= 50
1 <= Z <= 10^12
1 <= M <= 10^12
1 <= N <= 10^12
CODE:
#include <iostream>
using namespace std;
int chk_div(long long a,long long b)
{
if(((a/b) * (b) )==a)return 1;
return 0;
}
int main()
{
int t;
long i,j,count;
long n,m,z;
cin>>t;
while(t--)
{count=0;
cin>>z>>m>>n;
if(m>z)m=z;
if(n>z)n=z;
if (m>n)m=n;
for(i=1;i<=m;i++)
{
if(chk_div(z,i))count++;
}
cout<<count<<"\n";
}
return 0;
}
The main problem with performance here is the fact that your inner loop does about 10^12 iterations. You can reduce it a million times to sqrt(z) <= 10^6.
The trick here is to notice that Alice can write z = x * y if and only if he can write z = y * x. Also, either x <= sqrt(z) or y <= sqrt(z). Using these facts you can iterate only up to square root of z to count all cases.
I believe this should get the job done (idea from #zch's answer):
#include <iostream>
#include <cmath>
auto MAX = [] (int A, int B) -> bool { return A > B ? A : B; };
auto MIN = [] (int A, int B) -> bool { return A < B ? A : B; };
using std::cout;
using std::cin;
int main() {
long long Z, M, N, T, low, high, temp, div;
int ans;
for (cin >> T; T--; ) {
cin >> Z >> M >> N;
temp = MIN(M, N);
low = MIN(sqrt(Z), temp);
high = MAX(M, N);
for( ans = 0; low > 0 && (Z / low) <= high; --low ) {
if ( Z % low == 0) {
++ans;
div = Z / low;
ans += (div != low && div <= temp);
}
//cout << temp << " * " << Z / temp << " = " << Z << "\n";
}
cout << ans << "\n";
}
return 0;
}
Will be adding comments in a bit
Code with comments:
#include <iostream>
#include <cmath>
auto MAX = [] (int A, int B) -> bool { return A > B ? A : B; };
auto MIN = [] (int A, int B) -> bool { return A < B ? A : B; };
using std::cout;
using std::cin;
int main() {
long long Z, M, N, T, low, high, temp, div;
int ans;
for (cin >> T; T--; ) {
cin >> Z >> M >> N;
temp = MIN(M, N);
low = MIN(sqrt(Z), temp);//Lowest value <--We start iteration from this number
high = MAX(M, N); //Maximum value
for( ans = 0; low > 0 && (Z / low) <= high; --low ) {
//Number of things going on in this for-loop
//I will start by explaining the condition:
//We want to keep iterating until either low is below 1
// or when the expression (Z / low) > high.
//Notice that as the value of low approaches 0,
//the expression (Z / low) approaches inf
if ( Z % low == 0) {
//If this condition evaluates to true, we know 2 things:
/*Z is divisible by this value of low and
low is in the range of MIN(M,N) <--true*/
/*Because of our condition, (Z / low) is
within the range of MAX(M, N) <--true*/
++ans;
div = Z / low;
//This second part checks if the opposite is true i.e.
/*the value of low is in the range of
MAX(M, N) <--true*/
/*the value (Z / low) is in the range of
MIN(M, N) <--true only in some cases*/
ans += (div != low && div <= temp);
//(div != low) is to avoid double counting
/*An example of this is when Z, M, N have the values:
1000000, 1000000, 1000000
The value of low at the start is 1000 */
}
}
cout << ans << "\n";
}
return 0;
}
In fact, you have to resolve the problem in a different way:
find the Prime decomposition:
so Z = A^a * B^b * ... * P^p with A, B, .., P prime numbers
and so you just have to compute the number of possibilities from a, b, ... p.
(So the result is up to (1 + a) * (1 + b) * ... * (1 + p) depending of M&N constraints).
Your if(((a/b) * (b) ) == a) return 1; will always return 1. Why are you dividing A with B (a/b) then multiply the result by B. This is ambiguous because, your answer will be A. when you say, (a/b) * (b). B`s will cancel each other out and you are left with A as your answer. And so basically you are comparing if A == A, which is true.
Is there a way to build e.g. (853467 * 21660421200929) % 100000000000007 without BigInteger libraries (note that each number fits into a 64 bit integer but the multiplication result does not)?
This solution seems inefficient:
int64_t mulmod(int64_t a, int64_t b, int64_t m) {
if (b < a)
std::swap(a, b);
int64_t res = 0;
for (int64_t i = 0; i < a; i++) {
res += b;
res %= m;
}
return res;
}
You should use Russian Peasant multiplication. It uses repeated doubling to compute all the values (b*2^i)%m, and adds them in if the ith bit of a is set.
uint64_t mulmod(uint64_t a, uint64_t b, uint64_t m) {
int64_t res = 0;
while (a != 0) {
if (a & 1) res = (res + b) % m;
a >>= 1;
b = (b << 1) % m;
}
return res;
}
It improves upon your algorithm because it takes O(log(a)) time, not O(a) time.
Caveats: unsigned, and works only if m is 63 bits or less.
Keith Randall's answer is good, but as he said, a caveat is that it works only if m is 63 bits or less.
Here is a modification which has two advantages:
It works even if m is 64 bits.
It doesn't need to use the modulo operation, which can be expensive on some processors.
(Note that the res -= m and temp_b -= m lines rely on 64-bit unsigned integer overflow in order to give the expected results. This should be fine since unsigned integer overflow is well-defined in C and C++. For this reason it's important to use unsigned integer types.)
uint64_t mulmod(uint64_t a, uint64_t b, uint64_t m) {
uint64_t res = 0;
uint64_t temp_b;
/* Only needed if b may be >= m */
if (b >= m) {
if (m > UINT64_MAX / 2u)
b -= m;
else
b %= m;
}
while (a != 0) {
if (a & 1) {
/* Add b to res, modulo m, without overflow */
if (b >= m - res) /* Equiv to if (res + b >= m), without overflow */
res -= m;
res += b;
}
a >>= 1;
/* Double b, modulo m */
temp_b = b;
if (b >= m - b) /* Equiv to if (2 * b >= m), without overflow */
temp_b -= m;
b += temp_b;
}
return res;
}
Both methods work for me. The first one is the same as yours, but I changed your numbers to excplicit ULL. Second one uses assembler notation, which should work faster.
There are also algorithms used in cryptography (RSA and RSA based cryptography mostly I guess), like already mentioned Montgomery reduction as well, but I think it will take time to implement them.
#include <algorithm>
#include <iostream>
__uint64_t mulmod1(__uint64_t a, __uint64_t b, __uint64_t m) {
if (b < a)
std::swap(a, b);
__uint64_t res = 0;
for (__uint64_t i = 0; i < a; i++) {
res += b;
res %= m;
}
return res;
}
__uint64_t mulmod2(__uint64_t a, __uint64_t b, __uint64_t m) {
__uint64_t r;
__asm__
( "mulq %2\n\t"
"divq %3"
: "=&d" (r), "+%a" (a)
: "rm" (b), "rm" (m)
: "cc"
);
return r;
}
int main() {
using namespace std;
__uint64_t a = 853467ULL;
__uint64_t b = 21660421200929ULL;
__uint64_t c = 100000000000007ULL;
cout << mulmod1(a, b, c) << endl;
cout << mulmod2(a, b, c) << endl;
return 0;
}
An improvement to the repeating doubling algorithm is to check how many bits at once can be calculated without an overflow. An early exit check can be done for both arguments -- speeding up the (unlikely?) event of N not being prime.
e.g. 100000000000007 == 0x00005af3107a4007, which allows 16 (or 17) bits to be calculated per each iteration. The actual number of iterations will be 3 with the example.
// just a conceptual routine
int get_leading_zeroes(uint64_t n)
{
int a=0;
while ((n & 0x8000000000000000) == 0) { a++; n<<=1; }
return a;
}
uint64_t mulmod(uint64_t a, uint64_t b, uint64_t n)
{
uint64_t result = 0;
int N = get_leading_zeroes(n);
uint64_t mask = (1<<N) - 1;
a %= n;
b %= n; // Make sure all values are originally in the proper range?
// n is not necessarily a prime -- so both a & b can end up being zero
while (a>0 && b>0)
{
result = (result + (b & mask) * a) % n; // no overflow
b>>=N;
a = (a << N) % n;
}
return result;
}
You could try something that breaks the multiplication up into additions:
// compute (a * b) % m:
unsigned int multmod(unsigned int a, unsigned int b, unsigned int m)
{
unsigned int result = 0;
a %= m;
b %= m;
while (b)
{
if (b % 2 != 0)
{
result = (result + a) % m;
}
a = (a * 2) % m;
b /= 2;
}
return result;
}
a * b % m equals a * b - (a * b / m) * m
Use floating point arithmetic to approximate a * b / m. The approximation leaves a value small enough for normal 64 bit integer operations, for m up to 63 bits.
This method is limited by the significand of a double, which is usually 52 bits.
uint64_t mod_mul_52(uint64_t a, uint64_t b, uint64_t m) {
uint64_t c = (double)a * b / m - 1;
uint64_t d = a * b - c * m;
return d % m;
}
This method is limited by the significand of a long double, which is usually 64 bits or larger. The integer arithmetic is limited to 63 bits.
uint64_t mod_mul_63(uint64_t a, uint64_t b, uint64_t m) {
uint64_t c = (long double)a * b / m - 1;
uint64_t d = a * b - c * m;
return d % m;
}
These methods require that a and b be less than m. To handle arbitrary a and b, add these lines before c is computed.
a = a % m;
b = b % m;
In both methods, the final % operation could be made conditional.
return d >= m ? d % m : d;
I can suggest an improvement for your algorithm.
You actually calculate a * b iteratively by adding each time b, doing modulo after each iteration. It's better to add each time b * x, whereas x is determined so that b * x won't overflow.
int64_t mulmod(int64_t a, int64_t b, int64_t m)
{
a %= m;
b %= m;
int64_t x = 1;
int64_t bx = b;
while (x < a)
{
int64_t bb = bx * 2;
if (bb <= bx)
break; // overflow
x *= 2;
bx = bb;
}
int64_t ans = 0;
for (; x < a; a -= x)
ans = (ans + bx) % m;
return (ans + a*b) % m;
}