JuliaMelkozerova

HW3D

Mar 25th, 2020
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.06 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <utility>
  4. #include <algorithm>
  5.  
  6. using namespace std;
  7.  
  8. int start_period (vector <unsigned int> const & a, int N, int L) {
  9.     unsigned int length = 0;
  10.     int i, j;
  11.     for (i = 0; i < L; i++) {
  12.         for (j = i + 1; j < L ; j++) {
  13.             if (i >= N || j >= N)
  14.                 break;
  15.             if (a[j] == a[i])
  16.                 goto DoubleBreak;
  17.         }
  18.     }
  19.     return -1;
  20. DoubleBreak:
  21.     if (i == 0) return 0;
  22.     return i;
  23. }
  24.  
  25. int period_length (vector <unsigned int> const & a, int N, int L) {
  26.     int start = start_period(a, N, L);
  27.    
  28.     unsigned int length = 0;
  29.     int i, j;
  30.     for (i = 0; i < L; i++) {
  31.         for (j = i + 1; j < L ; j++) {
  32.             if (i >= N || j >= N)
  33.                 break;
  34.             if (a[j] == a[i])
  35.                 goto DoubleBreak;
  36.         }
  37.     }
  38. DoubleBreak:
  39.  
  40.     return j - i;
  41. }
  42.  
  43. int plain_sum (vector <unsigned int> & a, int N, int L) {  
  44.     int sum = 0;
  45.     bool odd = true;
  46.    
  47.     sort(a.begin(), a.end());  
  48.     for (int n = 0; n < N; n++) {
  49.         if (odd) {
  50.             sum += a[n] % L;
  51.             odd = false;
  52.         }
  53.         else odd = true;    
  54.     }
  55.     return sum % L;
  56. }
  57.  
  58. int fast_sum (vector <unsigned int> const & a, int N, int L) {
  59.     int length = period_length(a, N, L);
  60.        
  61.     vector <unsigned int> period(length);
  62.     for (int i = 0; i < length; i++)
  63.         period[i] = a[i];
  64.    
  65.     sort(period.begin(), period.end());
  66.    
  67.     unsigned int num_periods = N / length;
  68.     unsigned int period_remainder = N % length;
  69.    
  70.     int sum = 0;
  71.     bool odd = true;
  72.     for (int j = 0; j < period_remainder; j++) {
  73.         if (odd && (num_periods + 1) % 2) {
  74.             odd = false;
  75.             sum += ((num_periods + 1) / 2 + 1) * period[j] % L;
  76.         }
  77.         else if (!odd && (num_periods + 1) % 2) {
  78.             odd = true;
  79.             sum += ((num_periods + 1) / 2) * period[j] % L;
  80.         }
  81.         else if (!((num_periods + 1) % 2)) {
  82.             sum += ((num_periods + 1) / 2) * period[j] % L;
  83.         }
  84.     }
  85.     for (int j = period_remainder; j < length; j++) {
  86.         if (odd && num_periods % 2) {
  87.             odd = false;
  88.             sum += (num_periods / 2 + 1) * period[j] % L;
  89.         }
  90.         else if (!odd && num_periods % 2) {
  91.             odd = true;
  92.             sum += (num_periods / 2) * period[j] % L;
  93.         }
  94.         else if (!(num_periods % 2)) {
  95.             sum += (num_periods / 2) * period[j] % L;
  96.         }
  97.     }
  98.     return sum % L;
  99. }
  100.  
  101. int fast_sum_with_preperiod (vector <unsigned int> const & a, int N, int L) {
  102.     int start = start_period(a, N, L);
  103.     int length = period_length(a, N, L);
  104.    
  105.     vector <unsigned int> preperiod(start);
  106.     for (int i = 0; i < start; i++)
  107.         preperiod[i] = a[i];
  108.        
  109.     vector <unsigned int> period(length);
  110.     for (int i = 0; i < length; i++)
  111.         period[i] = a[i + start];
  112.    
  113.     sort(preperiod.begin(), preperiod.end());    
  114.     sort(period.begin(), period.end());
  115.    
  116.     unsigned int num_periods = (N - start) / length;
  117.     unsigned int period_remainder = (N - start) % length;
  118.    
  119.     int sum = 0;
  120.     bool odd = true;
  121.     int i = 0, j = 0;
  122.     while (i < start && j < length) {
  123.         if (preperiod[i] < period[j]) {
  124.             if (odd) {
  125.                 odd = false;
  126.                 sum += preperiod[i] % L;
  127.                 i++;
  128.             }
  129.             else {
  130.                 odd = true;
  131.                 i++;
  132.             }
  133.         }
  134.         else if (preperiod[i] > period[j]) {
  135.             if (j < period_remainder) {
  136.                 if (odd && (num_periods + 1) % 2) {
  137.                     odd = false;
  138.                     sum += ((num_periods + 1) / 2 + 1) * period[j] % L;
  139.                     j++;
  140.                 }
  141.                 else if (!odd && (num_periods + 1) % 2) {
  142.                     odd = true;
  143.                     sum += ((num_periods + 1) / 2) * period[j] % L;
  144.                     j++;
  145.                 }
  146.                 else if (!((num_periods + 1) % 2)) {
  147.                     sum += ((num_periods + 1) / 2) * period[j] % L;
  148.                     j++;
  149.                 }        
  150.             }
  151.             else if (j >= period_remainder) {
  152.                 if (odd && num_periods % 2) {
  153.                     odd = false;
  154.                     sum += (num_periods / 2 + 1) * period[j] % L;
  155.                     j++;
  156.                 }
  157.                 else if (!odd && num_periods % 2) {
  158.                     odd = true;
  159.                     sum += (num_periods / 2) * period[j] % L;
  160.                     j++;
  161.                 }
  162.                 else if (!(num_periods % 2)) {
  163.                     sum += (num_periods / 2) * period[j] % L;
  164.                     j++;
  165.                 }              
  166.             }
  167.         }
  168.         else if (preperiod[i] = period[j]) {
  169.             if (j < period_remainder) {
  170.                 if (odd && (num_periods + 2) % 2) {
  171.                     odd = false;
  172.                     sum += ((num_periods + 2) / 2 + 1) * period[j] % L;
  173.                     i++; j++;
  174.                 }
  175.                 else if (!odd && (num_periods + 2) % 2) {
  176.                     odd = true;
  177.                     sum += ((num_periods + 2) / 2) * period[j] % L;
  178.                     i++; j++;
  179.                 }
  180.                 else if (!((num_periods + 2) % 2)) {
  181.                     sum += ((num_periods + 2) / 2) * period[j] % L;
  182.                     i++; j++;
  183.                 }      
  184.             }
  185.             else if (j >= period_remainder) {
  186.                 if (odd && (num_periods + 1) % 2) {
  187.                     odd = false;
  188.                     sum += ((num_periods + 1) / 2 + 1) * period[j] % L;
  189.                     i++; j++;
  190.                 }
  191.                 else if (!odd && (num_periods + 1) % 2) {
  192.                     odd = true;
  193.                     sum += ((num_periods + 1) / 2) * period[j] % L;
  194.                     i++; j++;
  195.                 }
  196.                 else if (!((num_periods + 1) % 2)) {
  197.                     sum += ((num_periods + 1) / 2) * period[j] % L;
  198.                     i++; j++;
  199.                 }              
  200.             }            
  201.         }
  202.     }
  203.    
  204.     for (i; i < start; i++) {
  205.         if (odd) {
  206.             odd = false;
  207.             sum += preperiod[i] % L;
  208.         }
  209.         else odd = true;
  210.     }
  211.    
  212.     for (j; j < length; j++) {
  213.         if (j < period_remainder) {
  214.             if (odd && (num_periods + 1) % 2) {
  215.                 odd = false;
  216.                 sum += ((num_periods + 1) / 2 + 1) * period[j] % L;
  217.             }
  218.             else if (!odd && (num_periods + 1) % 2) {
  219.                 odd = true;
  220.                 sum += ((num_periods + 1) / 2) * period[j] % L;
  221.             }
  222.             else if (!((num_periods + 1) % 2)) {
  223.                 sum += ((num_periods + 1) / 2) * period[j] % L;
  224.             }
  225.         }
  226.         else {
  227.             if (odd && num_periods % 2) {
  228.                 odd = false;
  229.                 sum += (num_periods / 2 + 1) * period[j] % L;
  230.             }
  231.             else if (!odd && num_periods % 2) {
  232.                 odd = true;
  233.                 sum += (num_periods / 2) * period[j] % L;
  234.             }
  235.             else if (!(num_periods % 2)) {
  236.                 sum += (num_periods / 2) * period[j] % L;
  237.             }            
  238.         }
  239.     }
  240.     return sum % L;
  241. }
  242.  
  243. int main()
  244. {
  245.     unsigned int K;
  246.     int N, M, L, sum;
  247.     cin >> N >> K >> M >> L;
  248.    
  249.     vector <unsigned int> a(N);
  250.     a[0] = K;
  251.  
  252.     for (int i = 0; i < N - 1; i++)
  253.         a[i + 1] = (unsigned int)((a[i] * (unsigned long long)M) & 0xFFFFFFFFU) % L;
  254.    
  255.     /*for (int i = 0; i < N; i++)
  256.         cout << a[i] << ' ';
  257.     cout << endl;  */  
  258.    
  259.     int start = start_period(a, N, L);  
  260.     if (start == -1) {
  261.         sum = plain_sum(a, N, L);
  262.         cout << sum;
  263.         return 0;
  264.     }
  265.    
  266.     if (start == 0) {
  267.         sum = fast_sum (a, N, L);
  268.         cout << sum;
  269.         return 0;
  270.     }
  271.    
  272.     sum = fast_sum_with_preperiod(a, N, L);
  273.     cout << sum;
  274.     return 0;
  275. }
Advertisement
Add Comment
Please, Sign In to add comment