Truly choose your language
Although a C compiler won't accept the program as a whole (due to the using
directive and choice of headers) the actual code here is all really C. I'd make up my mind and either write C in a way that's acceptable to a C compiler, or else write C++ that makes good use of the language. The combination you've used is (IMO) pretty much a pit of despair.
For the remainder of this review, I'm going to go with the tag, and assume you really wanted to write good C++.
Avoid C's variadic I/O functions
Although some parts of the C library are fine, C's variadic I/O functions such as scanf and printf are quite problematic in one respect: they provide essentially no type safety. As shown by dozens (probably hundreds, if you looked carefully) of questions on Stack Overflow, mismatches between the formatting argument and the other arguments frequently cause problems. There are a few cases where you're reading or writing highly formatted data that it might be worth at least considering using these functions anyway, but the I/O format specified here doesn't provide any such justification.
Use the right types
In C++, there's rarely much reason to use a built in array such as your M
. You're usually better off with a std::array
or std::vector
instead.
Likewise, the values we need for inputs up to 40 can exceed the range of a 32-bit number. We probably want to use unsigned long long
(or something on the same general order) to support the specified range.
Names
As @NullException hinted at in the comments, most of the variable names in this code border on meaningless. I consider it perfectly acceptable to use a name like i
for a subscript in a loop, but for longer-lived things like your M
, a more meaningful name would be extremely helpful.
Consider a more recognizable algorithm
When you get down to it, what we're dealing with here is computing the least common multiple (LCM) of some numbers. There's a well-known method of computing the LCM of numbers: LCM(a, b) = a * b / gcd(a, b)
. This can be extended to three or more numbers quite easily:
LCM(a, b, c) =
L = lcm(a, b);
result = L * c / gcd(L,c)
Since this defines the LCM of three numbers in terms of the LCM of two numbers, we can extend it indefinitely.
Define functions where suitable
In this case, our definition of LCM depends on the GCD. Computing the GCD of two inputs is a well-defined operation that should probably be defined as a function.
Consider a greedy algorithm
In this case, we have only 40 possible inputs. We also have an algorithm for computing LCMs, where each result depends on the previous result. It's probably easiest to start by computing the LCM for every possible input from 1 to 40, then read the actual inputs, and just print out the result for each.
Result
Putting those suggestions together, we might get code something like this:
#include <map>
#include <vector>
#include <iostream>
template <class T>
T GCD(T u, T v) {
while (v != 0) {
T r = u % v;
u = v;
v = r;
}
return u;
}
int main() {
using T = unsigned long long;
std::vector<T> LCMs{ 1 }; // The LCM of 1 is 1
// Compute succeeding LCMs based on existing one(s)
for (T i = 2; i < 40; i++) {
auto prev = LCMs.back();
LCMs.push_back(prev * i / GCD(prev, i));
}
int test_count;
std::cin >> test_count;
for (int n = 0; n < test_count; n++) {
int input;
std::cin >> input;
std::cout << LCMs[input-1] << "\n";
}
}