Member 12847424 Ответов: 2

Как вы решите следующую проблему ?


Алексей пытается разработать программу для очень простого микроконтроллера. Он делает показания с различных датчиков с течением времени, и эти показания должны происходить в определенное регулярное время. К сожалению, если два из этих показаний происходят одновременно, микроконтроллер зависает и должен быть сброшен.

Существует N различных датчиков, которые регулярно считывают данные. Для каждого i от 1 до N считывание с датчика i будет происходить каждые Ai миллисекунд, причем первое считывание происходит ровно через Ai миллисекунд после включения микроконтроллера. Каждое считывание занимает ровно одну миллисекунду на микроконтроллере Алексея.

Алексей хочет знать, когда микроконтроллер замерзнет после того, как он его включит.

Ввод

Первая строка входных данных содержит целое число T, обозначающее количество тестовых случаев. Описание тестов t следующим образом.

Первая строка содержит одно целое число N, обозначающее количество датчиков.

Вторая строка содержит N целых чисел через пробел A1, A2,..., обозначающих частоту измерений. А именно, датчик i будет считываться каждые миллисекунды Ai, причем первое считывание происходит через миллисекунды Ai после первого включения микроконтроллера.

Выход

Для каждого тестового случая выведите одну строку, содержащую количество миллисекунд, пока микроконтроллер не замерзнет.

Ограничения
1 ≤ T ≤ 10
2 ≤ N ≤ 500
1 ≤ Ai ≤ 10^9

Пример
Ввод:
3
3
2 3 5
4
1 8 7 11
4
4 4 5 6

Выход:
6
7
4

А ограничение по времени - 1 секунда.

Что я уже пробовал:

Я придумал следующий код :-

#include<stdio.h>
 
int main(void)
{
    int t, n, i, flag;
    scanf("%d", &t);
 
    while(t--)
    {
        scanf("%d", &n);
        long a[n], time;
 
        scanf("%ld", &a[0]);
        time = a[0];
 
        for(i = 1; i < n; i++){
            scanf("%ld", &a[i]);
 
            if(a[i] < time)
                time = a[i];
        }
 
        flag = 0;
 
        while(flag != 2)
        {
            flag = 0;
 
            for(i = 0; i < n; i++)
            {
                if(time % a[i] == 0)
                    flag++;
 
                if(flag == 2)
                    break;
 
            }
 
 
            if(flag != 2)
                time++;
 
        }
 
        printf("%ld\n", time);
    }
 
    return 0;
}


Но лимит времени в 1 секунду превышен. Может ли кто-нибудь предложить более быстрый метод решения этой проблемы ?

Suvendu Shekhar Giri

есть успехи с отладкой?

Peter_in_2780

Вам нужно работать умнее, а не усерднее. Подумайте о том, почему два чтения происходят одновременно. Если это поможет, попробуйте несколько примеров с карандашом и бумагой.

KarstenK

код: long a[n], time; не компилируется. - Что это???

Совет: постарайтесь ограничить все входные данные.

2 Ответов

Рейтинг:
1

nv3

Если вы не можете решить проблему во всей ее сложности, попробуйте решить ее часть. В вашем случае это означает: попробуйте решить задачу за два таймера (N == 2). Когда они выстрелят в первый раз одновременно? Ответ: во время наименьшее общее кратное также называется наименьшее общее кратное (ЖК) Теперь, если вы погуглите это, вы обнаружите, что существует умный метод для расчета этого. И теперь у нас есть метод, чтобы вычислить это время для наших двух таймеров без необходимости проверять каждую миллисекунду! Как только мы получили это, мы можем обобщить это на N таймеров. Поэтому мы должны проверить каждый таймер на таймер друг друга. И когда вы посмотрите, как вычисляется ЖК-дисплей двух чисел, вы обнаружите, что наиболее трудоемкая часть этого процесса может быть разделена с предыдущими вычислениями. Так что это позволяет провести хорошую оптимизацию.

Итак, вот вам план действий:

1) Найдите в Google термин "наименьший общий делитель" и изучите его

2) осознайте, что задача для двух таймеров та же, что и поиск их наименьшего общего делителя

3) теперь решите свою проблему, рассчитав ЖК-дисплей для каждой пары таймеров

4) оптимизируйте свое решение, извлекая наиболее трудоемкую часть (факторизацию) и сделайте это только один раз.

Это, безусловно, сократит ваше время расчета до 500 пар таймеров (около 125.000 жидкокристаллических вычислений) до менее чем секунды.

Если у вас есть проблемы с любым из этих четырех шагов, вы можете задать вопрос именно об этом. Но никто не будет (или не должен) преподносить вам решение на блюдечке с голубой каемочкой. Это твой домашнее задание и должно помочь ты чтобы чему-то научиться, а не нам.


Рейтинг:
0

Patrice T

С

long a[n], time;

, размер a[n] устанавливается во время компиляции. Это будет прекрасно работать, если n было установлено значение 500, но это было не так. Ваш n устанавливается во время выполнения, и в этом случае, a должен быть указатель на массив, и массив должен быть выделен динамически во время выполнения.
Динамические массивы: использование malloc () и realloc () - учебники по C/C++ - Codecall[^]
C выделение памяти с помощью malloc (), calloc (), free () и realloc()[^]
[^]

Лопоки вроде вас используют метод грубой силы, чтобы найти 2 датчика Колизея. Тебе нужно поумнеть.
Если датчик срабатывает каждые 300000 МС (5 м), а другой-каждые 720000 МС (12 м), будете ли вы проверять каждые миллисекунды или у вас есть более умный способ определить, что следующее столкновение произойдет через 1 час ?


Member 12847424

Я полностью согласен с тем, что вы сказали о проверке каждой миллисекунды, но проблема в том, что я не могу найти способ обуздать ненужную проверку на наличие столкновений.

Patrice T

Каждое считывание датчика происходит на кратном периоде.
Вы получаете столкновение, когда время кратно периоду 2 датчиков одновременно.