A prime p is fixed. A sequence of n numbers is given, each from 1 to p - 1. It is known that the numbers in the sequence are chosen randomly, equally likely and independently from each other. Choose some numbers from the sequence so that their product, taken modulo p, is equal to the given number x. If no numbers are selected, the product is considered equal to one.
Input:
The first line contains three integers separated by spaces: the length of the sequence n, the prime number p and the desired value x
(n=100, 2<=p<=10^9, 0<x<p)
Next, n integers are written, separated by spaces or line breaks: the sequence a1, a2,. . ., an
(0 <ai <p)
Output:
Print the numbers from the sequence whose product modulo p is equal to x. The order in which numbers are displayed is not important. If there are several possible answers, print any of them
Example:
INPUT:
100 11 4
9 6 1 1 10 4 9 10 3 1 10 1 6 8 3 3 9 8
10 3 7 7 1 3 3 1 5 2 10 4 1 5 6 7 2 6
2 8 3 3 6 7 6 3 1 5 10 2 2 10 9 6 8 6
2 10 3 2 7 4 3 2 8 6 4 1 7 2 10 8 4 9
7 9 8 7 4 7 3 2 8 2 3 7 1 5 2 10 7 1 8
6 4 10 10 3 6 10 2 1
OUTPUT:
4 6 10 9
My solution:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n,p,x,y,m,k,tmp;
vector<int> v;
cin >> n >> p >> x;
for (int i = 0; i<n; i++){
cin >> tmp;
v.push_back(tmp);
}
sort(v.begin(), v.end());
v.erase(v.begin(), upper_bound(v.begin(), v.end(), 1));
k=-1;
while(1){
k++;
m = 1;
y = x+p*k;;
vector<int> res;
for (int i = 0; i<n; i++){
if (y == 1) break;
if ( y%v[i] == 0){
res.push_back(v[i]);
m*=v[i];
m%=p;
y = y/v[i];
}
}
if (m==x) {
for (int i = 0; i<res.size(); i++){
cout << res[i] << " ";
}
break;
}
}
return 0;
}
In my solution, I used condition (y=x+k*p, where y is the product of numbers in the answer, and k is some kind of natural number). And also iterated over the value k.
This solution sometimes goes beyond the allotted time. Please tell me a more correct algorithm.
I would consider a backtracking routine over the hashed multiset of the input list. Since p is a prime, at any point we can consider if the current multiple, m, has (multiplicative_inverse(m, p) * x) % p in our multiset (https://en.wikipedia.org/wiki/Multiplicative_inverse). If it exists, we're done. Otherwise, try multiplying either by the same number we are currently visiting in the multiset, or by the next one (keep the result of the multiplication modulo p).
Please see comment below for a link to example code in Python. The example you gave has trivial solutions so it would be helpful to have some non-trivial, as well as challenging examples to test and refine on. Please also clarify if more than one number is expected in the output.
You can use dynamic programming approach. It requires O(p) memory cells and O(p*n) loop iterations. There is possible several optimization (to exclude processing input duplicates, or print longest/shortest selection chain). Following is simplest and basic DP-program, demonstrating this approach.
#include <stdio.h>
#include <stdlib.h>
int data[] = {
9, 6, 1, 1, 10, 4, 9, 10, 3, 1, 10, 1, 6, 8, 3, 3, 9, 8,
10, 3, 7, 7, 1, 3, 3, 1, 5, 2, 10, 4, 1, 5, 6, 7, 2, 6,
2, 8, 3, 3, 6, 7, 6, 3, 1, 5, 10, 2, 2, 10, 9, 6, 8, 6,
2, 10, 3, 2, 7, 4, 3, 2, 8, 6, 4, 1, 7, 2, 10, 8, 4, 9,
7, 9, 8, 7, 4, 7, 3, 2, 8, 2, 3, 7, 1, 5, 2, 10, 7, 1, 8,
6, 4, 10, 10, 3, 6, 10, 2, 1
};
struct elm {
int val; // Value
int prev; // from which elemet we come to this
int n; // add loop cound for prevent multiple use same val
};
void printsol(int n, int p, int x, const int *in) {
struct elm *dp = (struct elm *)calloc(p, sizeof(struct elm));
int i, j;
for(i = 0; i < n; i++) // add initial elements into DP array
dp[in[i]].val = in[i];
for(i = 0; i < n; i++) { // add elements, one by one, to DP array
if(dp[in[i]].val <= 1) // skip secondary "1" multipliers
continue;
for(j = 1; j < p; j++)
if(dp[j].val != 0 && dp[j].n < i) {
int y = ((long)j * in[i]) % p;
dp[y].val = in[i]; // current value, for printout
dp[y].prev = j; // reference to prev element
dp[y].n = n; // loop num, for prevent double reuse
if(x == y && dp[x].n > 0) {
// targed reached - print result, by iterate linklist
int mul = 1;
while(x != 0) {
printf(" %d ", dp[x].val);
mul *= dp[x].val; mul %= p;
x = dp[x].prev;
}
printf("; mul=%d\n", mul);
free(dp);
return;
}
} // for+if
} // for i
free(dp);
}
int main(int argc, char **argv) {
printsol(100, 11, 4, data);
return 0;
}
Related
#include <iostream>
using namespace std;
int main()
{
const int ARRAY_SIZE = 10;
int value[ARRAY_SIZE] = { 1, 2, 3, 4, 3, 4, 2, 3, 5, 6};
int value2[100];
for (int i = 0; i < ARRAY_SIZE; i++)
{
for (int j = i + 1; j <= ARRAY_SIZE; j++)
{
if (value[i] == value[j])
{
cout << value[i] << " ";
}
}
}
return 0;
}
The output is
2 3 3 4 3
How can I make the output become 2 3 4 ?
Edit: I'm trying to print all numbers appearing more than once in the value array
I think I should create one more array to store value, but I stuck with it and don't know how to do it.
It helps considerably to sort your array. Then you only need two indices:
a write index, starting at 0
a read index, starting at 1
Loop over your array using the read index. For every array[read] that has a duplicate value at array[read-1], IFF that value also does not exist at array[write], then copy it over and increment your write index.
Finally, the new length of your data is equal to your write index.
The basic idea is this: if I have a sorted list of values:
1 3 3 4 5 5 5 7 7 9
Then I can easily see if a value is a duplicate or not by comparing the current (read) with the previous.
┌────┐
1 3 3 │4 5│ 5 5 7 7 9 -- not duplicates
└────┘
↑
┌────┐
1 3 3 4 │5 5│ 5 7 7 9 -- duplicate values
└────┘
↑
The only remaining trick is to make just a single copy of that value to the write index, which we can do by simply looking at the last thing we wrote.
You can use a std::map to count the number of times a value is in the array. If the number appears 2 or more times, then print it.
#include <iostream>
#include <map>
int main()
{
const int ARRAY_SIZE = 10;
int value[ARRAY_SIZE] = { 1, 2, 3, 4, 3, 4, 2, 3, 5, 6};
std::map <int, int> mp;
for(int i : value)
++mp[i];
for(const auto& p : mp)
if(p.second > 1)
std::cout << p.first << ' ';
}
Link.
I'm trying to find the frequency of elements in an array. I have found lots of programs on Google that can do just this, but I can't get them to count right for my array.
This is the code I use:
#include <iostrem>
#include <cmath>
const int nmax = 50;
int main() {
int afk[nmax], count;
const int N = 40;
int dn[N] = { 6, 1, 2, 1, 5, 3, 1, 0, 3, 1, 2, 3, 6, 2, 1, 1, 5, 5, 1, 5, 0, 1, 3, 0, 0, 1, 0, 2, 1, 0, 0, 3, 1, 5, 2, 1, 4, 1, 0, 3 };
for (int i = 0; i < N; i++) {
afk[i] = -1;
}
for (int i = 0; i < N; i++) {
count = 1;
for (int j = i + 1; j < N; j++) {
if (dn[i] == dn[j]) {
count++;
afk[j] = 0;
}
}
if (afk[i] != 0) afk[i] = count;
}
for (int i = 0; i <= 6; i++) {
if (afk[i] != 0) {
cout << endl << i << " | " << afk[i];
}
}
}
This gives the output:
0 | 2
1 | 13
2 | 5
4 | 5
5 | 6
But I know this is worng and the right answer is
0 | 8
1 | 13
2 | 5
3 | 6
4 | 1
5 | 5
6 | 2
So the code only gets the frequency of elemnet 1 and 2 right.
Can anyone tell what's wrong with this code?
You are counting the frequencies just fine (well, not as efficiently as you could be), but you are not displaying them correctly.
The afk[] array is storing each number's frequency at the same index as its first occurrence in the dn[] array.
In your final display loop, you are printing the loop counter i itself instead of printing the number at the i'th index of the dn[] array. So, if you change this:
cout << endl << i << " | " << afk[i];
To this:
cout << endl << dn[i] << " | " << afk[i];
Then you will get a more meaningful result:
6 | 2
1 | 13
2 | 5
5 | 5
3 | 6
Note that the frequencies of 0 and 4 are missing, though. The first occurrence of 0 in the dn[] array is at index 7, and the first occurrence of 4 is at index 36. But your display loop stops after index 6, which is why it does not display the frequencies of 0 and 4. You would need to loop over the entire afk[] array to fix that, then you will see the missing entries:
6 | 2
1 | 13
2 | 5
5 | 5
3 | 6
0 | 8
4 | 1
Demo
However, the results are not sorted by number, as you want. To fix that, you will have to either:
sort the dn[] array before counting its frequencies (which, incidentally, will help make counting easier).
change the afk[] array to hold a struct type that contains int number and int frequency members, and then you can sort afk[] on number after counting the frequencies.
if nmax is greater than the largest number in the dn[] array (ie, > 6 in this case), then your counting loop can simply use the number stored at dn[i] as the index into afk[] rather than using i as the index. Then your display loop can simply display the afk[] array as-is (I suspect this is what you originally meant to do). Demo
In which case, it would be far easier to count the frequencies using a std::map instead, and let it handle the counting and sorting for you, eg:
#include <iostream>
#include <map>
using namespace std;
int main() {
map<int, int> afk;
int dn[40] = {6, 1, 2, 1, 5, 3, 1, 0, 3, 1, 2, 3, 6, 2, 1, 1, 5, 5, 1, 5, 0, 1, 3, 0, 0, 1, 0, 2, 1, 0, 0, 3, 1, 5, 2, 1, 4, 1, 0, 3};
for(auto number : dn){
afk[number]++;
}
for(auto &p : afk){
cout << p.first << " | " << p.second << endl;
}
}
0 | 8
1 | 13
2 | 5
3 | 6
4 | 1
5 | 5
6 | 2
Demo
I'm having a trouble for a long time in a problem related to array and loops.
Assume an array like:
int arr[] = {2, 3, 5, 3, 6, 8, 10, 1, 9};
The program should print the expected column as shown (note that the table is an idea for clarification of what I actually want to achieve):
max: expected arr[index] for max
------------------------------------
2 : 3 5 value of: arr[0]
3 : 6, 8, 10 value of: arr[3]
1 : 9 value of: arr[7]
This is what I've tried so far:
#include <iostream>
int main(void) {
int arr[] = {2, 3, 5, 3, 6, 8, 10, 1, 9};
int max = arr[0];
int i = 1, it = i;
for (; i <= max; i++) {
if (i == max) {
std::cout << arr[i] << std::endl;
max = arr[it + 1]; // when loop end has come, increment max to next element value
it = i + 2; // incrementing iterator by 2 next element position (after max)
} else {
std::cout << arr[i] << ' '; // when loop is executing
}
}
return 0;
}
What it actually prints which is unexpected V/S what it should print:
3 5 | 3, 5
3 6 8 | 6, 8, 10
10 1 9 | 1, 9
10 | <nothing>
The program is about to get max value and print the next elements until max value reaches the number of element position.
Where the problem's occurring and how to fix it? Please let me know.
So I rewrote your code, frankly I couldn't follow it, it seems a bit confused with variable names that seem a bit off.
Here's some working code. The two key concepts in the code are the place where each block starts (the variable start) and the size of each block (the variable count). Plus I use the size of the whole array sizeof(arr)/sizeof(arr[0]) to terminate the outer loop. Something that wasn't present in your code. If you are using C++17, you can use std::size(arr) instead of sizeof.
int main(void) {
int arr[] = {2, 3, 5, 3, 6, 8, 10, 1, 9};
size_t start = 0;
while (start < sizeof(arr)/sizeof(arr[0]))
{
int count = arr[start];
for (int i = 0; i < count; ++i)
{
std::cout << arr[start + i + 1] << ' ';
}
std::cout << std::endl;
start += count + 1;
}
}
The output is
3 5
6 8 10
9
Bellow is a simple template array implementation using malloc and realloc
Stepping through with a debugger, there were less code steps than vector.
However, when timing using std::chrono, std::vector is still faster.
Why is this?
(Compiling using gnu cc v9)
#include <../array.hpp>
#include <../console.hpp>
#include <vector>
int main() {
console::time("array");
array<int> a { 1, 2, 3, 4, 5, 6, 7 };
console::timeEnd("array");
for (unsigned int i = 0; i < a.size(); i++) {
console::log(std::to_string(a[i]));
}
array<int> b { 1, 2, 3, 4, 5, 6, 8 };
if (a != b) {
console::log("a != b");
}
array<int> c { 1, 2, 3, 4, 5, 6, 7 };
if (a == c) {
console::log("a == c");
}
console::time("std::vector");
vector<int> v { 1, 2, 3, 4, 5, 6, 7 };
console::timeEnd("std::vector");
for (unsigned int i = 0; i < v.size(); i++) {
console::log(std::to_string(v[i]));
}
return 0;
};
array: 27µs - timer ended
1
2
3
4
5
6
7
a != b
a == c
std::vector: 2655ns - timer ended
1
2
3
4
5
6
7
Full implementation [here](https://gist.github.com/universefullofthings/ac933d64158217478a02df7bdcc8f319?.
How is the y.size() = 4 in the following? The values in y are {11, 2, 4, 7} How does one arrive at this? What are a and b in the operator() function for each iteration of the set. I don't understand the construction of y and I can't find anything online that explains this situation. Thank You
#include <iostream>
#include <set>
struct C
{
bool operator()(const int &a, const int &b) const
{
return a % 10 < b % 10;
}
};
int main()
{
std::set<int> x({ 4, 2, 7, 11, 12, 14, 17, 2 });
std::cout << x.size() << std::endl;
std::set<int, C> y(x.begin(), x.end());
std::cout << y.size() << std::endl;
std::set<int>::iterator iter;
for (iter = y.begin(); iter != y.end(); ++iter)
{
std::cout << *iter << std::endl;
}
return 0;
}
Second template argument of set is comparator type — type of functor that implements less operation.
struct C
{
bool operator()(const int &a, const int &b) const
{
return a % 10 < b % 10;
}
};
This comparator will compare a and b as a < b only if a % 10 < b % 10, so practically all numbers will be compared by modulo 10.
UPDATE:
After pushing into x set numbers { 4, 2, 7, 11, 12, 14, 17, 2 }, set will contain seven elements { 2, 4, 7, 11, 12, 14, 17 }. These elements will be sorted in that way, because set stores objects in sorted way.
Then numbers from x set are being sequentially inserted into y set. Before inserting of each element, set will find proper place in sorted order of currently inserted numbers. If set will see, that there is already some number on it's place, set will not insert it.
After inserting {2, 4, 7} from x to y, y will be {2, 4, 7}.
Then, to insert 11 into y set will do comparisons of 11 with {2, 4, 7} to find proper place using provided C functor.
To check is 11 less than 2 set will call C()(11, 2), which will result in 11 % 10 < 2 % 10 comparison, which will result in true, so 11 will be inserted before 2.
Other numbers from x (12, 14, 17) will not be inserted, because set will find, that 12 should be on place of 2 (because 2 % 10 < 12 % 10 or 12 % 10 < 2 % 10 expression is false, so 2 == 12), and in same way 14 and 17.