Update
Идущий с двоичного поиска подход, здесь мой новый код:
// compute X/ai sum
long long summarize(long long ar[], long long n, long long X)
{
long long sum = 0;
for (long long i = 0; i < n; i++)
{
sum += X/ar[i];
}
return sum;
}
bool get_range(long long ar[], int n, int m, pair<long long, long long>& range)
{
long long sum = 0;
long long x;
// reduce range
while (range.first < range.second)
{
x = (range.first + range.second)/2;
sum = summarize(ar, n, x);
if (sum < m)
{
range.first = x + 1;
}
else if (sum > m)
{
range.second = x;
}
else if (x == range.first)
{
return true; // single element
}
else
{
break;
}
}
if (sum != m)
{
return false;
}
// check surroundings for lower/upper bound.
sum = summarize(ar, n, range.first);
if (sum != m)
{
auto r1 = make_pair(range.first + 1, x);
if (get_range(ar, n, m, r1))
{
range.first = r1.first;
}
else
{
range.first = x;
}
}
sum = summarize(ar, n, range.second - 1);
if (sum != m)
{
auto r2 = make_pair(x + 1, range.second - 1);
if (get_range(ar, n, m, r2))
{
range.second = r2.second;
}
else
{
range.second = x + 1;
}
}
return true;
}
int main()
{
int n, m;
cin >> n >> m;
long long *ar = new long long[n];
long long ar_min = LLONG_MAX;
for(long long i = 0; i < n; i++)
{
cin >> ar[i];
ar_min = min(ar[i], ar_min);
}
// initial range of possible X values
auto range = make_pair(m/(ar_min * n), m * ar_min);
if (get_range(ar, n, m, range))
{
cout << (range.second - range.first) << endl;
}
else
{
cout << 0 << endl;
}
}
Функциональность ядра - это функция get_range
, которая принимает возможный диапазон ([range.first, range.second)
, поэтому вторая - , а не часть диапазона) и уменьшает диапазон, поэтому все элементы в диапазоне удовлетворяют условию. Сначала выполняется итеративная корректировка границ диапазона до тех пор, пока середина диапазона не станет частью результата или пока не станет ясно, что результата нет. Затем, если есть какой-либо результат, он рекурсивно проверяет поддиапазоны ниже и выше найденного результата, чтобы получить границы всего диапазона результатов.
Version 1
Вы имеете дело только с положительными числами больше нуля.
M = floor(X/a1) + floor(X/a2) + ... + floor(X/an)
Для каждого суб-термина floor(X/a1)
, есть floor(X1/ai) <= floor(X2/ai)
если X1 < X2
. Таким образом, единственными возможными значениями X
, приводящими к M
, являются те, где floor(X1/ai) == floor(X2/ai)
для всех i
(или все ai
).
Для каждого ai
это точно диапазон X1=k*ai
до X2=k*ai+(ai-1)
для некоторых k
.
Это означает, что если какое-либо решение существует, диапазон значений X будет находиться между k*min(ai)
и (k+1)*min(ai)
для некоторых 0 < k <= m
.
Так что, возможно, стоит сначала получить диапазон возможных результатов, а затем проверить отдельные значения только в пределах диапазона.
Результирующий алгоритм:
// compute X/ai sum
long long summarize(long long ar[], long long n, long long X)
{
long long sum = 0;
for (long long i = 0; i < n; i++)
{
sum += X/ar[i];
}
return sum;
}
int main()
{
int n, m;
cin >> n >> m;
long long *ar = new long long[n];
long long ar_min = LLONG_MAX;
for(long long i = 0; i < n; i++)
{
cin >> ar[i];
ar_min = min(ar[i], ar_min);
}
// lowest possible k
long long k = m/(ar_min * n);
// get the value k for a possible range of X values
for (; k <= m; k++)
{
auto x = ar_min * (k + 1);
long long sum = summarize(ar, n, x);
if (sum > m)
{
break;
}
}
long long X_min = k * ar_min, X_max = (k + 1) * ar_min;
long long result = 0;
// count possible X values
for (long long x = X_min; x < X_max; x++)
{
long long sum = summarize(ar, n, x);
if (sum == m)
{
++result;
}
else if (sum > m)
{
break;
}
}
cout << result << endl;
}
Он получил немного более сложным, чем я ожидал. Надеюсь, это все еще какое-то улучшение.
Можете ли вы предоставить ссылку вопрос? –
@User_Targaryen Вопрос написан на моем родном языке и у местного онлайн-судьи. Доказательство ссылки не поможет. Если вы действительно хотите узнать хотя [link] (https://training.ia-toki.org/training/curriculums/1/courses/11/chapters/53/problems/247/). – SangBijaksana
Действительно ли возможно иметь несколько значений X, удовлетворяющих этому уравнению? я думаю, что только один возможен (если вообще возможно), нет? – mangusta