Advertisement
welleyth

IOI2017 Camp. C

May 9th, 2023
564
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.65 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;
  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;
  39.     }
  40.     /// if is_zero, then is_negative = false
  41. public:
  42.     myInt():cnt2(0),cnt3(0),is_negative(false),is_zero(false){
  43.         cnt3 = 0;
  44.         is_negative = true;
  45.     }
  46.     myInt(int x):cnt2(0),cnt3(0),is_negative(false),is_zero(false){
  47.         if(x == 0)
  48.             is_zero = true;
  49.         else if(x < 0)
  50.             is_negative = true;
  51.         if(abs(x) == 2)
  52.             cnt2 = 1;
  53.         else if(abs(x) == 3)
  54.             cnt3 = 1;
  55.     }
  56.     myInt(const myInt& other){
  57.         this->cnt2 = other.cnt2;
  58.         this->cnt3 = other.cnt3;
  59.         this->is_negative = other.is_negative;
  60.         this->is_zero = other.is_zero;
  61.     }
  62.     myInt& operator=(const myInt& other){
  63.         this->cnt2 = other.cnt2;
  64.         this->cnt3 = other.cnt3;
  65.         this->is_negative = other.is_negative;
  66.         this->is_zero = other.is_zero;
  67.         return *this;
  68.     }
  69.     friend
  70.     bool operator<(const myInt& a,const myInt& b){
  71.         if(a.lessZero() && b.biggerEqualZero()){
  72.             return true;
  73.         }
  74.         if(a.lessEqualZero() && b.biggerZero()){
  75.             return true;
  76.         }
  77.         if(a.biggerEqualZero() && b.lessEqualZero()){
  78.             return false;
  79.         }
  80.         if(a.lessEqualZero() && b.lessEqualZero()){
  81.             return (a.cnt2-b.cnt2) - (b.cnt3 - a.cnt3) * LOG2_3 > eps;
  82.         } else {
  83.             return (a.cnt2-b.cnt2) - (b.cnt3 - a.cnt3) * LOG2_3 < eps;
  84.         }
  85.     }
  86.     bool operator>(const myInt& other){
  87.         if(lessEqualZero() && other.biggerEqualZero()) /// <= 0 ? >= 0
  88.             return false;
  89.         if(biggerEqualZero() && other.lessZero()) /// >= 0 && < 0
  90.             return true;
  91.         if(lessEqualZero() && other.lessEqualZero()){
  92.             return (cnt2-other.cnt2) - (other.cnt3 - cnt3) * LOG2_3 < eps;
  93.         } else {
  94.             return (cnt2-other.cnt2) - (other.cnt3 - cnt3) * LOG2_3 > eps;
  95.         }
  96.     }
  97.     friend
  98.     myInt operator*(const myInt& a,const myInt& b){
  99.         myInt result = a;
  100.         result.cnt2 += b.cnt2;
  101.         result.cnt3 += b.cnt3;
  102.         result.is_negative ^= b.is_negative;
  103.         result.is_zero |= b.is_zero;
  104. //        if(result.is_zero){
  105. //            result.is_zero = true;
  106. //            result.cnt2 = result.cnt3 = 0;
  107. //            result.is_negative = false;
  108. //        }
  109.         return result;
  110.     }
  111.     friend
  112.     istream& operator>>(istream& o,myInt& x){
  113.         int value;
  114.         o >> value;
  115.         x = myInt(value);
  116.         return o;
  117.     }
  118.     int getValue(){
  119.         if(is_zero) return 0;
  120.         int x = 1;
  121.         for(int i = 0; i < cnt2; i++) x = (1ll * x * 2) % md;
  122.         for(int i = 0; i < cnt3; i++) x = (1ll * x * 3) % md;
  123.         if(is_negative) x = md - x;
  124.         return x;
  125.     }
  126. };
  127.  
  128. myInt a[501][501];
  129. myInt dp[2][501][501];
  130.  
  131. myInt st[2][10][501];
  132. int n,m,k;
  133.  
  134. myInt getMin(int l,int r){
  135.     l = max(1ll,l);
  136.     r = min(m,r);
  137.     int j = __lg(r - l + 1);
  138.     return min(st[1][j][l],st[1][j][r-(1<<j)+1]);
  139. }
  140.  
  141. myInt getMax(int l,int r){
  142.     l = max(1ll,l);
  143.     r = min(m,r);
  144.     int j = __lg(r - l + 1);
  145.     return max(st[0][j][l],st[0][j][r-(1<<j)+1]);
  146. }
  147.  
  148. void solve(){
  149. //    assert(myInt(-3) < myInt(3));
  150. //    assert(myInt(-2) < myInt(3));
  151. //    assert(myInt(-1) < myInt(3));
  152. //    assert(myInt(0) < myInt(3));
  153. //    assert(myInt(1) < myInt(3));
  154. //    assert(myInt(2) < myInt(3));
  155. //    assert(!(myInt(3) < myInt(3)));
  156. //
  157. //    assert((myInt(2)*myInt(2)).getValue() == 4);
  158. //    assert((myInt(2)*myInt(3)).getValue() == 6);
  159. //    assert((myInt(-2)*myInt(3)).getValue() == md-6);
  160. //
  161. //    return;
  162.     cin >> n >> m >> k;
  163.  
  164.     for(int i = 1; i <= n; i++){
  165.         for(int j = 1; j <= m; j++){
  166.             cin >> a[i][j];
  167.         }
  168.     }
  169. //
  170. //    for(int i = 1; i <= n; i++){
  171. //        for(int j = 1; j <= m; j++){
  172. //            cout << a[i][j].getValue() << " ";
  173. //        }
  174. //        cout << "\n";
  175. //    }
  176.  
  177.     for(int t = 0; t < 2; t++){
  178.         for(int i = 1; i <= n; i++){
  179.             for(int j = 1; j <= m; j++){
  180.                 dp[t][i][j].cnt3 = n+1;
  181.                 dp[t][i][j].is_negative = !t;
  182.             }
  183.         }
  184.     }
  185.  
  186.     for(int i = 1; i <= m; i++){
  187.         dp[0][1][i] = dp[1][1][i] = a[1][i];
  188.     }
  189.  
  190.     for(int i = 2; i <= n; i++){
  191.         for(int j = 1; j <= m; j++){
  192.             st[0][0][j] = dp[0][i-1][j];
  193.             st[1][0][j] = dp[1][i-1][j];
  194.         }
  195.         for(int t = 1; t < 10; t++){
  196.             for(int j = 1; j + (1 << t) - 1 <= m; j++){
  197.                 st[0][t][j] = max(st[0][t-1][j],st[0][t-1][j+(1<<(t-1))]);
  198.                 st[1][t][j] = min(st[1][t-1][j],st[1][t-1][j+(1<<(t-1))]);
  199.             }
  200.         }
  201.         for(int j = 1; j <= m; j++){
  202.             myInt maxVal = getMax(j-k,j+k);
  203.             myInt minVal = getMin(j-k,j+k);
  204.             if(dp[0][i][j] < maxVal * a[i][j]) dp[0][i][j] = maxVal * a[i][j];
  205.             if(dp[0][i][j] < minVal * a[i][j]) dp[0][i][j] = minVal * a[i][j];
  206.             if(dp[1][i][j] > maxVal * a[i][j]) dp[1][i][j] = maxVal * a[i][j];
  207.             if(dp[1][i][j] > minVal * a[i][j]) dp[1][i][j] = minVal * a[i][j];
  208.         }
  209.     }
  210.  
  211. //    for(int i = 1; i <= n; i++){
  212. //        for(int j = 1; j <= m; j++){
  213. //            cout << dp[1][i][j].getValue() << " ";
  214. //        }
  215. //        cout << "\n";
  216. //    }
  217.  
  218.     myInt maxVal = dp[0][n][1];
  219.     for(int i = 1; i <= m; i++){
  220.         maxVal = max(maxVal,dp[0][n][i]);
  221.     }
  222.     cout << maxVal.getValue() << "\n";
  223.  
  224.     return;
  225. }
  226.  
  227. signed main(){
  228.     ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
  229. //  freopen("output.txt","w",stdout);
  230.     int tests = 1;
  231.     cin >> tests;
  232.     for(int test = 1; test <= tests; test++){
  233. //        cout << "Case #" << test << ": ";
  234.         solve();
  235.     }
  236.     return 0;
  237. }
  238. /**
  239. 2
  240.  
  241. 1
  242. 2
  243. 2 1
  244.  
  245. 3
  246.  
  247. 1
  248. 2
  249. 3
  250. 2 1
  251. 3 1
  252. 3 2
  253. 2 3
  254.  
  255. 3 1 -> phi(3) = 2
  256. 3 2
  257.  
  258.  
  259. **/
  260.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement