Advertisement
welleyth

IOI camp 2017. C

May 9th, 2023 (edited)
658
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.36 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. //#define int long long
  6. #define mp make_pair
  7. #define pb push_back
  8.  
  9. constexpr int N = (int)1e6 + 111;
  10. constexpr int md = (int)1e9+7;
  11. constexpr int INF = (int)2e9;
  12. constexpr int inv6 = 175000002;
  13. constexpr double eps = 1e-7;
  14. constexpr double LOG2_3 = log2((double)3);
  15.  
  16. #pragma GCC optimize("O3")
  17. #pragma GCC optimize("unroll-loops")
  18. #pragma GCC target("avx2")
  19.  
  20. void add(int& a,int b){
  21.     a = (a + b >= md ? a + b - md : a + b);
  22. }
  23.  
  24. class myInt{
  25. public:
  26.     int cnt2, cnt3;
  27.     bool is_negative, is_zero;
  28.     bool lessZero() const{
  29.         return is_negative && !is_zero;
  30.     }
  31.     bool lessEqualZero() const{
  32.         return is_negative || is_zero;
  33.     }
  34.     bool biggerZero() const{
  35.         return !is_negative && !is_zero;
  36.     }
  37.     bool biggerEqualZero() const{
  38.         return !is_negative || is_zero;
  39.     }
  40. public:
  41.     myInt():cnt2(0),cnt3(0),is_negative(false),is_zero(false){
  42.         cnt3 = 502;
  43.         is_negative = true;
  44.     }
  45.     myInt(int x):cnt2(0),cnt3(0),is_negative(false),is_zero(false){
  46.         if(x == 0)
  47.             is_zero = true;
  48.         else if(x < 0)
  49.             is_negative = true;
  50.         x = abs(x);
  51.         while(x > 0 && x % 2 == 0) x /= 2, cnt2++;
  52.         while(x > 0 && x % 3 == 0) x /= 3, cnt3++;
  53.     }
  54.     myInt(const myInt& other){
  55.         this->cnt2 = other.cnt2;
  56.         this->cnt3 = other.cnt3;
  57.         this->is_negative = other.is_negative;
  58.         this->is_zero = other.is_zero;
  59.     }
  60.     myInt& operator=(const myInt& other){
  61.         this->cnt2 = other.cnt2;
  62.         this->cnt3 = other.cnt3;
  63.         this->is_negative = other.is_negative;
  64.         this->is_zero = other.is_zero;
  65.         return *this;
  66.     }
  67.     friend
  68.     bool operator<(const myInt& a,const myInt& b){
  69.         if(a.is_zero && b.is_zero)
  70.             return false;
  71.         if(a.is_zero || b.is_zero){
  72.             if(a.is_zero)
  73.                 return b.biggerZero();
  74.             if(b.is_zero)
  75.                 return a.lessZero();
  76.         }
  77.         if(a.lessZero() && b.biggerEqualZero())
  78.             return true;
  79.         if(a.lessEqualZero() && b.biggerZero())
  80.             return true;
  81.         if(a.biggerEqualZero() && b.lessEqualZero())
  82.             return false;
  83.         if(a.lessEqualZero() && b.lessEqualZero()){
  84.             return (a.cnt2-b.cnt2) - (b.cnt3 - a.cnt3) * LOG2_3 > eps;
  85.         } else {
  86.             return (a.cnt2-b.cnt2) - (b.cnt3 - a.cnt3) * LOG2_3 < eps;
  87.         }
  88.     }
  89.     friend
  90.     myInt operator*(const myInt& a,const myInt& b){
  91.         myInt result = a;
  92.         result.cnt2 += b.cnt2;
  93.         result.cnt3 += b.cnt3;
  94.         result.is_negative ^= b.is_negative;
  95.         result.is_zero |= b.is_zero;
  96.         if(result.is_zero){
  97.             result.is_zero = true;
  98.             result.cnt2 = result.cnt3 = 0;
  99.             result.is_negative = false;
  100.         }
  101.         return result;
  102.     }
  103.     friend
  104.     istream& operator>>(istream& o,myInt& x){
  105.         int value;
  106.         o >> value;
  107.         x = myInt(value);
  108.         return o;
  109.     }
  110.     int getValue() const{
  111.         if(is_zero) return 0;
  112.         int x = 1;
  113.         for(int i = 0; i < cnt2; i++) x = (1ll * x * 2) % md;
  114.         for(int i = 0; i < cnt3; i++) x = (1ll * x * 3) % md;
  115.         if(is_negative) x = md - x;
  116.         return x;
  117.     }
  118. };
  119.  
  120. myInt a[501][501];
  121. myInt dp[2][501][501];
  122. myInt st[2][11][501];
  123. int n,m,k;
  124.  
  125. myInt getMin(int l,int r){
  126.     l = max(1,l);
  127.     r = min(m,r);
  128.     int j = __lg(r - l + 1);
  129.     return min(st[1][j][l],st[1][j][r-(1<<j)+1]);
  130. }
  131.  
  132. myInt getMax(int l,int r){
  133.     l = max(1,l);
  134.     r = min(m,r);
  135.     int j = __lg(r - l + 1);
  136.     return max(st[0][j][l],st[0][j][r-(1<<j)+1]);
  137. }
  138.  
  139. void solve(int test){
  140.     cin >> n >> m >> k;
  141.     for(int i = 1; i <= n; i++){
  142.         for(int j = 1; j <= m; j++){
  143.             cin >> a[i][j];
  144.         }
  145.     }
  146.     for(int t = 0; t < 2; t++){
  147.         for(int i = 1; i <= n; i++){
  148.             for(int j = 1; j <= m; j++){
  149.                 dp[t][i][j] = myInt();
  150.                 dp[t][i][j].is_negative = !t;
  151.             }
  152.         }
  153.     }
  154.  
  155.     for(int i = 1; i <= m; i++){
  156.         dp[0][1][i] = dp[1][1][i] = a[1][i];
  157.     }
  158.  
  159.     for(int i = 2; i <= n; i++){
  160.         for(int j = 1; j <= m; j++){
  161.             st[0][0][j] = dp[0][i-1][j];
  162.             st[1][0][j] = dp[1][i-1][j];
  163.         }
  164.         for(int t = 1; t < 11; t++){
  165.             for(int j = 1; j + (1 << t) - 1 <= m; j++){
  166.                 st[0][t][j] = max(st[0][t-1][j],st[0][t-1][j+(1<<(t-1))]);
  167.                 st[1][t][j] = min(st[1][t-1][j],st[1][t-1][j+(1<<(t-1))]);
  168.             }
  169.         }
  170.         for(int j = 1; j <= m; j++){
  171.             myInt maxVal = getMax(j-k,j+k);
  172.             myInt minVal = getMin(j-k,j+k);
  173.             if(dp[0][i][j] < maxVal * a[i][j]) dp[0][i][j] = maxVal * a[i][j];
  174.             if(dp[0][i][j] < minVal * a[i][j]) dp[0][i][j] = minVal * a[i][j];
  175.             if(maxVal * a[i][j] < dp[1][i][j]) dp[1][i][j] = maxVal * a[i][j];
  176.             if(minVal * a[i][j] < dp[1][i][j]) dp[1][i][j] = minVal * a[i][j];
  177.         }
  178.     }
  179.     cout << max_element(&dp[0][n][1],&dp[0][n][m+1])->getValue() << "\n";
  180.     return;
  181. }
  182.  
  183. signed main(){
  184.     ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
  185.     int tests = 1;
  186.     cin >> tests;
  187.     for(int test = 1; test <= tests; test++){
  188.         solve(test);
  189.     }
  190.     return 0;
  191. }
  192. /**
  193. **/
  194.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement