Advertisement
bs9o

15-2

May 25th, 2018
321
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.14 KB | None | 0 0
  1. //главное, что используется в задаче: (a + b) mod n = ((a mod n) + (b mod n)) mod n
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <limits.h>
  6. #include <malloc.h>
  7. #include <stdlib.h>
  8.  
  9. int dp[100001][100], remainders[10000]; //массив, в котором отмечаем "ходы", и массив остатков соответственно
  10.  
  11. int divisibility(int n, int k, int i, int sum) {
  12.     int plus, minus, t;
  13.     sum = (sum % k + k) % k; //берем остаток от деления очередной суммы; замечание, про которое я говорил: мы пишем (sum % k + k) % k, а не просто sum % k, чтобы остаток всегда был неотрицательный, и это существенно, иначе будет неправильно работать.(В си нет стандарта на неотрицательный остаток. Так, -20 % 9 == -2, а нам надо, чтобы было 7.)
  14.     if (i == n) {
  15.         if (sum == 0) return 1;
  16.         return 0;
  17.     } //i == n значит, что все элементы последовательности были пройдены и добавлены в сумму с тем или иным знаком
  18.     if (dp[i][sum] != -1) return dp[i][sum]; //здесь проверяем, была ли раньше посчитана дальнейшая сумма; если была, то из рекурсии выходим на шаг назад
  19.     plus = divisibility(n, k, i + 1, sum + remainders[i]); //пробуем плюс
  20.     minus = divisibility(n, k, i + 1, sum - remainders[i]); //пробуем минус
  21.     t = (plus | minus);
  22.     dp[i][sum] = t; //запоминаем, что уже посчитали какой-то случай в рекурсии
  23.     return t;
  24. } //итого: функция вернет 1, если последовательность остатков делится на k, 0 - иначе
  25.  
  26. int main() {
  27.     freopen("input.txt", "r", stdin);
  28.     freopen("output.txt", "w", stdout);
  29.     int i, j, t, n, k;
  30.     i = 0;
  31.     scanf("%d %d", &n, &k);
  32.     for (i = 0; i < n; i++) {
  33.         for (j = 0; j < k; j++) dp[i][j] = -1;
  34.     }
  35.     i = 0;
  36.     while (scanf("%d", &t) != EOF) {
  37.         if (t % k != 0) {
  38.             remainders[i] = t % k;
  39.             i++;
  40.         }
  41.     } //немного облегчим задачу: будем искать делимость не изначальной последовательности, а последовательности из остатков(можно, в общем-то, делать то же самое с обычной последовательностью)
  42.     if (i == 0) printf("Divisible");
  43.     else if (i == 1) printf("Not divisible"); //два тривиальных случая, когда на вход подается только одно число
  44.     else (divisibility(i, k, 1, remainders[0]) ? printf("Divisible") : printf("Not divisible")); //на вход в функцию подаем: i - количество остатков, k - число, деление на которое проверяем, 1 - номер первого шага, remainders[0] - первая сумма
  45. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement