2008, TCHS, Весна, Раунд 1, День декораций (DecorationDay)

 

Двое играют в следующую игру. Первый игрок разложил несколько кучек монет перед вторым и просит его выбрать одну или несколько групп монет. При этом НОД (наибольший общий делитель) количества монет в выбранных группах должен равняться 1. Например, из кучек {2, 3, 4} можно выбрать {2, 3} или {2, 3, 4}, но никак не {2, 4}.

Массив groups описывает количество монет в кучках. Необходимо определить количество способов, которыми второй игрок может сделать выбор кучек.

 

Класс: DecorationDay

Метод: int howMany(vector<int> groups)

Ограничения: groups содержит от 1 до 50 элементов, 1 £ groups[i] £ 100000.

 

Вход. Массив groups, описывающий количество монет в кучках.

 

Выход. Количество способов, которыми второй игрок может сделать выбор кучек.

 

Пример входа

groups

{2, 4, 3}

{2, 2, 2, 4}

{2, 2, 3}

{2, 5, 98872, 23298, 32872, 23111}

{1}

 

Пример выхода

3

0

3

45

1

 

 

РЕШЕНИЕ

динамическое программирование

 

Обозначим через d[i][x] количество подмножеств из i первых кучек, для которых НОД равен x. В таком случае ответом будет значение d[n][1], где n – количество групп.

Поскольку подмножества из (i + 1) первых кучек включают в себя все подмножества из i первых кучек, то значение d[i][x]  следует добавить к d[i + 1][x] для каждого x.

Пусть НОД некоторого подмножества из i первых кучек равен x. При добавлении к нему (i + 1) - го элемента НОД полученного подмножества станет равным НОД(x, groups[i]) (индексы массива groups начинаются с нуля, первым элементом массива является groups[0]). Поэтому значение d[i][x] следует добавить к d[i + 1][НОД(x, groups[i])].

Перед началом обработки (i + 1) - ой кучки следует увеличить на 1 значение d[i + 1][groups[i]]: если игрок выберет только одну, (i + 1) - ую кучку, то НОД количества монет в выбранных кучках равен groups[i].

Рассмотрим заполнение ячеек d[i][x] для случая, когда groups = {2, 4, 3}:

i \ x

1

2

3

4

0

0

0

0

0

1

0

1

0

0

2

0

2

0

1

3

3

2

1

1

 

При groups = {2, 5, 3, 4} массив d будет иметь вид:

i \ x

1

2

3

4

5

0

0

0

0

0

0

1

0

1

0

0

0

2

1

1

0

0

1

3

4

1

1

0

1

4

10

2

1

1

1

 

ПРОГРАММА

 

#include <cstdio>

#include <vector>

#include <memory>

using namespace std;

 

long long d[51][100001];

 

int gcd(int a, int b)

{

  return a ? gcd(b%a,a) : b;

}

 

class DecorationDay

{

public:

  int howMany(vector<int> groups)

  {

    int i,j,n=(int)groups.size();

    memset(d,0,sizeof(d));

    for(i=1;i<=n;i++)

    {

      d[i][groups[i-1]]++;

      for(j=1;j<=100000;j++)

      {

        d[i][gcd(j,groups[i-1])] += d[i-1][j];

        d[i][j] += d[i-1][j];

      }

    }

    return d[n][1] % 10000003;

  }

};