I have a class Node
class Node
{
public:
int Number;
char Ch;
Node(int N, char A)
{
Number = N;
Ch = A;
}
};
that I want to sort as follows. First sort by the Number, and if the numbers, are equal, place the one with the Character as "M" in front.
bool Srt(Node A, Node B)
{
if (A.Number < B.Number)
return true;
if (A.Number > B.Number)
return false;
if (A.Number == B.Number)
{
if (B.Ch == 'M')
{
return true;
}
return false;
}
return false;
}
However, this does not work properly for the following input:
1 S
2 S
3 S
4 S
5 S
6 S
7 S
8 S
9 S
10 S
11 S
12 S
13 S
14 S
15 S
16 S
999999985 M
999999986 M
999999987 M
999999988 M
999999989 M
999999990 M
999999991 M
999999992 M
999999993 M
999999994 M
999999995 M
999999996 M
999999997 M
999999998 M
999999999 M
1000000000 M
It should return the list again but instead it returns
1 S
2 S
3 S
4 S
5 S
6 S
7 S
8 S
9 S
999999993 M
999999994 M
999999995 M
999999996 M
999999997 M
999999998 M
999999999 M
1000000000 M
10 S
11 S
12 S
13 S
14 S
15 S
16 S
999999985 M
999999986 M
999999987 M
999999988 M
999999989 M
999999990 M
999999991 M
999999992 M
It looks like you have implemented a less-than comparison for use with std::sort.
Such a comparator needs to be a strict weak ordering, such that A < B implies !( B < A ). Your function violates this if the numbers are equal and both have character M. Try this instead:
if (A.Number < B.Number)
return true;
if (A.Number > B.Number)
return false;
// Now A.Number == B.Number so there is no need to check.
return B.Ch == 'M' && A.Ch != 'M';
Related
Given integers C and N, (c <= n <= 10^9), find the amount of pairs i,j (n >= i >= j >= 1), where gcd(i,j) == C
long long gcd(long long int a, long long int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
void solve(int tt){
int c,n;
cin >> c >> n;
ll ans = 0;
for(int i = 1; i <= n; i++){
for(int j = i; j <= n; j++){
if(gcd(i,j) == c) ans++;
}
}
cout << ans;
return;
}
This is getting timed out and I've tried various different ways to try and fix it - nothing is working... Does anyone know the code to optimize this? (Output %100000007)
"Given integers C and N, (c <= n <= 10^9), find the amount of pairs i,j (n >= i >= j >= 1), where gcd(i,j) == C"
We can divide everything by C to get:
How many integers i and j satisfy: 2 <= j < i <= n/c, and are relatively prime?
Let's check a few:
n/c count (new pairs listed in parens)
<=2 0
3 1 (2,3)
4 2 (3,4)
5 5 (2,5), (3,5), (4,5)
6 6 (5,6)
7 11 (2,7), (3,7), (4,7), (5,7), (6,7)
8 14 (3,8), (5,8), (7,8)
9 19 (2,9), (4,9), (5,9), (7,9), (8,9)
Each time we increment i, we can pair it with all smaller values of j >= 2 that don't have any of the same factors. For primes this is all smaller values of j >= 2.
This is https://oeis.org/A015613.
Here's an approach courtesy of geeksforgeeks:
Find the count of smaller integers >= 2 relatively prime to n, also known as Euler's totient function, in O(sqrt(n) * log(n)) time as follows:
1) Initialize result as n
2) Consider every number 'p' (where 'p' varies from 2 to Φn).
If p divides n, then do following
a) Subtract all multiples of p from 1 to n [all multiples of p
will have gcd more than 1 (at least p) with n]
b) Update n by repeatedly dividing it by p.
3) If the reduced n is more than 1, then remove all multiples
of n from result.
Add these up for 2 through n in O((n^1.5) * log(n)) time.
I want to print out all possible n number subsets out of given n*3 numbers (random numbers within int). We also assume that n is small enough to do brute force. And for simplicity I assume n = 7.
P.S. We do not take number in the same position twice. So, if I have n*3 numbers like: 1,2,3,4,5,6 etc. n*3 I cannot use "1" twice and 1 1 2 3 4 5 6 is invalid way to ttake n-numbers.
But if I have n*3 numbers like 1 1 2 2 3 3 4 4 5 5 6 6 7 7 etc. then I can use "1" twice and one way to choose 7-numbers is 1 1 2 3 4 5 6.
I can do it in stupid way like this assuming n = 7.
int n = 7;
int n3 = 21;
for (int j = 0; j < n3; j++) {
for (int k = 0; k < n3; k++) {
if (j == k) {
break;
}
for (int l = 0; l < n3; l++) {
if ((l == k) || (j == l)) {
break;
}
for (int m = 0; m < n3; m++) {
if ((m == l) || (m == k) || (m == j)) {
break;
}
... etc.
How can this can be rewritten using some data structures?
I am at school and I have just started learning algorithms. I have basic C++ knowledge and some basic data structures knowledge (array, vector, queue, set, map).
Take n elements from m can be done with std::next_permutation:
template <typename F, typename T>
void CnP(F f, const std::vector<T>& elems, std::size_t n)
{
std::vector<bool> v(n, true);
v.resize(elems.size(), false); // { true, .., true, false, .., false}
do {
f(elems, v);
} while (std::prev_permutation(v.begin(), v.end()));
}
Demo
I'm quite new to C++ (but know my way around C) so I'm probably missing something obvious.
TLDR: I use a std::set which stores elements twice, which is definitely not what I want.
Long story:
I've defined a class Clique and I need to store elements of this class in a set, so I've defined the < operator for Clique:
class Clique{
public :
int b;
int e;
int l;
std::set<int> X;
bool operator <( const Clique &rhs ) const
{
if( b < rhs.b)
return true;
if( e < rhs.e)
return true;
if( X.size() < rhs.X.size() )
return true;
std::set<int>::iterator itX = X.begin();
std::set<int>::iterator itrhs = rhs.X.begin();
// both sets have same size, need only to check end for one of them
while( (*itX == *itrhs) && ( itX != X.end() ) ){
++itX;
++itrhs;
}
if( itX == X.end() ){
//both sets are equal
return false;
}
else
return ( *itX < *itrhs );
}
void print_clique(FILE *F) const ;
};
(I wasn't sure how set comparison is done, so I wrote a routine for comparing them first by size, then element by element).
Now I want to store Clique elements in a set and this is where the problem appears.
My std::set
(1) does not appear to store Clique elements in the order I've defined;
(2) stores several copies of the same Clique
I've written a function to print a set of Clique:
void print_cliqueset(std::set<Clique> mySet){
int setsize = 0;
std::set<Clique>::iterator it = mySet.begin();
Clique cur_c = *it;
Clique prev_c = *it;
while( it != mySet.end() ){
// for( std::set<Clique>::iterator it = mySet.begin(); it != mySet.end(); ++it ){
it->print_clique(stdout);
setsize ++;
++it;
if( it != mySet.end() ){
cur_c = *it;
assert ( prev_c < cur_c);
gassert( prev_c.b <= cur_c.b );
prev_c = *it;
}
}
assert( setsize == mySet.size() );
}
My function is more complicated than needed but I wanted to make sure I understood what was going on.
Here is a typical output of printing such a set:
There's a line for each Clique, in which I print first b, then e, then the elements in the set X.
6829 9716 1 2 3 5 8 9 10
6792 9687 1 2 3 7 8 9 10
606 6531 1 2 3 5 6 7 8 9
6829 9687 1 2 3 5 7 8 9 10
410 9951 2 6
484 9805 1 2 4 6
494 9805 2 4 6 10
506 9805 1 2 5 6
484 9821 1 2 4
484 9871 2 3 4 6
506 9821 1 2 5
484 9802 1 2 3 4 6
486 9805 1 2 4 6 9
486 9802 1 2 3 4 6 9
507 9802 1 2 3 4 6 9 10
502 9802 1 2 3 4 6 10
506 9802 1 2 3 5 6
507 9806 1 2 4 9 10
507 9805 1 2 5 6 9
527 9806 1 2 5 9 10
As we can see, the cliques are not at all sorted on the order I defined (or wanted to define). They should be sorted first by member b (which is the first of each line), and this is not the case at all.
Then I have some duplicate lines in the output (not appearing in the example above but present in the full output). I guess the fact that I have duplicates is not surprising given that it seems confused about the order...
I guess the answer is something fairly obvious but I fail to see it. Any help would be appreciated!
Your bool operator <( const Clique &rhs ) const is wrong as it doesn't respect strict ordering.
It may simply be:
bool operator <(const Clique& rhs) const
{
return std::tie(b, e, X) < std::tie(rhs.b, rhs.e, rhs.X);
}
Your operator< is broken. Consider two Cliques:
c1 is {b = 0, e = 1, ...}
c2 is {b = 1, e = 0, ...}
Your code will return true for both c1 < c2 and c2 < c1.
Obviously, in such situation std::set shows strange behavior.
I would fix your operator< in the following way:
bool operator <( const Clique &rhs ) const
{
if( b != rhs.b)
return b < rhs.b;
if( e != rhs.e)
return e < rhs.e;
if( X.size() != rhs.X.size() )
return X.size() < rhs.X.size();
std::set<int>::iterator itX = X.begin();
std::set<int>::iterator itrhs = rhs.X.begin();
// both sets have same size, need only to check end for one of them
while((itX != X.end()) && (itX == *itrhs)){
++itX;
++itrhs;
}
if( itX == X.end() ){
//both sets are equal
return false;
}
else
return ( *itX < *itrhs );
}
The definition of operator< should be such that for each pair of elements 'b' and 'e' the relationship b < e should be used to determine any kind of relationship. The following equivalences are in force here:
a > b <==> b < a
a == b <==> !(a < b) && !(b < a)
a >= b <==> `!(a < b)
And so on. If you use multiple fields to be checked for every relationship check, then you have a kind-of multidimensional ranges. Making a flat range out of that can be only done this way:
More significant field is checked first; if in this field values aren't equal, you return the result immediately
Otherwise - if they are equal - you check the next field in the significance order and so on.
The requirement of using this complicated relationship definition in the set makes things actually harder for you because all you should do is to state whether one element is less than the other. So in your case you'll have to check for equality inside by yourself. Your procedure checks the fields "next in significance chain" also if lhs.b > rhs.b.
Operator < must provide strict weak ordering. I.e. if x < y then !(y < x) and !(y == x).
In the case of Clique, the requirements seem to be that the elements b, e, and X are compared lexographically.
The idiomatic way to represent this is to do all comparisons in terms of operator<:
#include <set>
class Clique{
public :
int b;
int e;
int l;
std::set<int> X;
bool operator <( const Clique &r ) const
{
auto const& l = *this;
if (l.b < r.b) return true;
if (r.b < l.b) return false;
if (l.e < r.e) return true;
if (r.e < l.e) return false;
if (l.X < r.X) return true;
if (r.X < l.X) return false;
return false;
}
void print_clique(FILE *F) const ;
};
And yes, std::set really does provide operator< when the key type provides it.
Another way to write this, as Jarod was alluding to is this:
#include <set>
#include <tuple>
class Clique{
public :
int b;
int e;
int l;
std::set<int> X;
bool operator <( const Clique &r ) const
{
auto const& l = *this;
return std::tie(l.b, l.e, l.X) < std::tie(r.b, r.e, r.X);
}
void print_clique(FILE *F) const ;
};
Which I think you'll agree is concise, expressive, correct and idiomatic.
I have a problem with one task, so if you could help me a little bit.
Numbers are "lucky" or "unlucky". Number is "lucky" just if every
digit 7
or every digit is 4. So "lucky" numbers are for example 4, 44, 7, 77.
"Unlucky" are the others numbers.
You will get sequence of n-elements and number K. Your task is to
compute number of all possible k-elements subsequence, which fulfill a one
condition. The condition is that in the subsequence mustn't be two same "lucky"
numbers. So for example there mustn't 77 and 77...
Output number of all possible k-elements subsequence mod 10^9+7
0 < N,K < 10^5
Few examples:
Input:
5 2
7 7 3 7 77
Output:
7
Input:
5 3
3 7 77 7 77
Output:
4
Input:
34 17
14 14 14 ... 14 14 14
Output:
333606206
I have code which seems to work, but it is too slow when I try to compute binomial coefficient. I'm using map. In string I store number in string format. In second - int - part of the map is number which represents how many times was that number(in the first map parameter) used. So now I have stored every "unlucky" numbers stored together. Also every same "lucky" number is together. When I have it stored like this, I just compute all multiplications. For example:
Input
5 2
3 7 7 77 7
Are stored like this: map["other"] = 1 map["7"] = 3 map["77"] = 1
Because k = 2 --> result is: 1*3 + 1*1 + 1*3 = 7.
I think problem is with computing binomial coefficient. For the third example it needs to compute (34 choose 17) and it is computing very long time.I've found this article and also this , but I don't understand how they are solving this problem.
My code:
#include<iostream>
#include<string>
#include<map>
#include <algorithm>
#include <vector>
using namespace std;
int binomialCoeff(int n, int k)
{
// Base Cases
if (k == 0 || k == n)
return 1;
// Recur
return binomialCoeff(n - 1, k - 1) + binomialCoeff(n - 1, k);
}
int main()
{
int n, k;
cin >> n >> k;
map<string, int> mapa; // create map, string is a number, int represents number of used string-stored numbers ---> so if 7 was used two times, in the map it will be stored like this mapa["7"] == 2 and so on)
for (int i = 0; i < n; i++) // I will load number as string, if this number is "lucky" - digist are all 7 or all 4
{ // every "unlucky" numbers are together, as well as all same "lucky" numbers ---> so 77 and 77 will be stored in one element....
string number;
cin >> number;
char digit = number[0];
bool lucky = false;
if (digit == '7' || digit == '4')
lucky = true;
for (int j = 1; j < number.length(); j++) {
if (digit != '7' && digit != '4')
break;
if (number[j] != digit) {
lucky = false;
break;
}
}
if (lucky)
mapa[number]++;
else
mapa["other"]++;
}
vector<bool> v(mapa.size());
bool lack = k > mapa.size(); //lack of elements in map --> it is when mapa.size() < k; i. e. number of elements in array can't make k-element subsequence.
int rest = lack ? k - mapa.size() + 1 : 1; // how many elements from "unlucky" numbers I must choose, so it makes base for binomial coefficient (n choose rest)
if (lack) //if lack is true, different size of vector
fill(v.begin() + mapa.size(), v.end(), true);
else
fill(v.begin() + k, v.end(), true);
int *array = new int[mapa.size()]; //easier to manipulate with array for me
int sum = 0;
int product = 1;
int index = 0;
for (map<string, int> ::iterator pos = mapa.begin(); pos != mapa.end(); ++pos) // create array from map
{
if (lack && pos->first == "other") { //if lack of elements in map, the number in elemets representing "unlucky" numbers will be binomial coefficient (mapa["other] choose rest)
array[index++] = binomialCoeff(mapa["other"], rest);
continue;
}
array[index++] = pos->second;
}
do { // this will create every posible multiplication for k-elements subsequences
product = 1;
for (int i = 0; i < mapa.size(); ++i) {
if (!v[i]) {
product *= array[i];
}
}
sum += product;
} while (next_permutation(v.begin(), v.end()));
if (mapa["other"] >= k && mapa.size() > 1) { // if number of "unlucky" numbers is bigger than k, we need to compute all possible k-elements subsequences just from "unlucky" number, so binomial coefficient (mapa["other] choose k)
sum += binomialCoeff(mapa["other"], k);
}
cout << sum % 1000000007 << endl;
}
Well, I have to write a program to find the NEAREST number of given number N which has exactly "K" 7s.
For example, if input is:
N K
1773 3
Output:
1777
Oh, one more thing is that N can be 100 000 000 000 000 maximum, will long long be enough to handle this?
My code so far which is not working :(
#include <iostream>
using namespace std;
int main()
{
unsigned long long a, i;
int b, num=0, dig, tmp;
cin>>a>>b;
i=a+1;
do
{
num=0;
tmp=i;
while (tmp>0)
{
dig=tmp%10;
tmp=tmp/10;
if (dig==7)
num++;
}
i++;
}
while(num<b);
cout<<i-1;
return 0;
}
Your problem is not a programming problem but a math problem.
Let m = 1+E(log10(N)), ie the number of digits in the decimal writing of N (it will be probably faster to compute it by counting digits than using a logarithm).
Let mK be the number of 7 in N.
Let N' be the output number.
I see 4 cases:
K >= m : then N' = 7..7 (K digits).
K == mK : then N' = N.
K > mK and K < m : then you replace all non-7 digits with 7, starting from the least significant digits. Ex: N = 1 357 975 , K = 4 => N' = 1 357 777. Warning : there is a special case, if you have a 8, ex: N = 80, N' = 79. You can do this case by using a common prefix, and then generating an all 7 suffix (special case: remove one more from the prefix and add 7 9 7 7 ... 7). See special case in the code.
K < mK : there are two possible numbers.
Lets decompose N: N = a1 a2 ... ap 7 b1 b2 ... bq, where
a1 ... ap are p numbers in [0..9] and
b1 ... bq are q numbers in [0..9] \ {7}
Let A = a1 ... ap 6 9 ... 9 and B = a1 ... ap 8 0 ... 0 (q digits after the 6or the 8). Then, N' = closestToN(A,B). If both numbers are equally close, the choice is up to you.
Sorry for the bad math formatting.
The code can now be more easy to write. Here is my implementation:
#include <iostream>
unsigned long long getClosestWith7(unsigned long long n, unsigned int k)
{
// Count number of digits
unsigned long long tmp = n;
unsigned int m = 0, mK = 0;
while(tmp > 0)
{
if(tmp % 10 == 7) mK++;
tmp /= 10;
m++;
}
// Distinct cases
if(k == mK && n != 0)
return n;
else if(k >= m || n == 0) // implicit: k != mK
{
unsigned long long r = 0;
while(k > 0)
{
r = 10 * r + 7;
k--;
}
return r;
}
else if(k > mK) // implicit: k != mK, k < m
{
unsigned long long r = n;
unsigned long long s = 0;
m = 0;
while(mK < k)
{
if(r % 10 != 7) mK++;
r /= 10;
m++;
}
if(r % 10 == 8) // special case
s = 79 + 100 * (r / 10);
while(m > 0)
{
r = 10 * r + 7;
if(s != 0 && m > 1) // special case
s = 10 * s + 7;
m--;
}
return (r < n && n - r < n - s) || (r >= n && r - n < n - s) ? r : s;
}
else // implicit : k < mK
{
// Generate a and b
unsigned long long a = n;
unsigned long long b = 0;
m = 0;
while(mK > k)
{
if(a % 10 == 7) mK--;
a /= 10;
m++;
}
b = 10 * a + 8;
a = 10 * a + 6;
m--;
while(m > 0)
{
a = 10 * a + 9;
b = 10 * b + 0;
m--;
}
// Compare (return lowest if equal)
return n - a <= b - n ? a : b;
}
}
#define CLOSEST7( N , K ) \
std::cout << "N = " << N << ", K = " << K << " => N' = " << getClosestWith7(N,K) << "\n"
int main()
{
CLOSEST7(1773,3);
CLOSEST7(83,1);
CLOSEST7(17273,3);
CLOSEST7(1273679750,6);
CLOSEST7(1773,1);
CLOSEST7(83,5);
CLOSEST7(0,2);
CLOSEST7(0,0);
}
For your question about long long: it depends on the compiler. Often, the size of this type is 64 bits, so you can store number from 0 to 2^64 - 1 (unsigned), which is 18 446 744 073 709 551 615, so it should be ok for your data range on most implementations.
Some problems:
ans=i records some i after you've divided it a few times, you need to record the original i
You only loop in 1 direction, you need to check in both directions at the same time
Looping through all numbers is fundamentally too slow
If the number is 100 000 000 000 000 and k = 14, you'd need to check 22 222 222 222 223 (100 000 000 000 000-77 777 777 777 777) numbers, which is not viable
Side note - the maximum for long long is 9223372036854775807.
Here is some pseudo-code which should work:
num = number of 7s in input
if (num == k)
print input
if (num < k)
a = input with (k-num) non-7 digits from least significant digit set to 7
let x = last position set
b = substring(input, 1, position)
c = b + 1
d = b - 1
ba = concat(b, substring(a, position, end))
ca = concat(c, substring(a, position, end))
da = concat(d, substring(a, position, end))
if (abs(input - ba) <= abs(input - ca) &&
abs(input - ba) <= abs(input - da))
print b
else
if (abs(input - ca) <= abs(input - ba) &&
abs(input - ca) <= abs(input - da))
print c
else
print d
if (num > k)
x = (k-num)th 7 from least significant digit
a = input with x set to 6 and all less significant digits to 9
b = input with x set to 8 and all less significant digits to 0
if (input - a > b - input)
print b
else
print a
How about this algorithm?
Convert the number into a string.
Count the number of 7s in it.
If it has less 7s than K, change the numbers from the right-most to left into 7s one-by-one until K is reached, then go to step 5.
If it has more 7s than K, change the numbers from the right-most to left into 6s one-by-one only if they are 7, until K is reached, then go to step 5.
Convert it back into an integer.
long long is usable according to Dukeling's answer.