Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <numeric>
- #include <algorithm>
- #include <set>
- #include <map>
- #include <queue>
- #include <cassert>
- #include <vector>
- #include <string>
- using namespace std;
- typedef long long ll;
- vector<vector<int> > horizontal_fold(vector<vector<int> > v)
- {
- int h = v.size();
- int w = v[0].size();
- vector<vector<int> > res(h/2, vector<int>(w));
- for(int i=0;i<h/2;i++)
- for(int j=0;j<w;j++)
- res[i][j] = v[i][j] + v[h-1-i][j];
- return res;
- }
- vector<vector<int> > vertical_fold(vector<vector<int> > v)
- {
- int h = v.size();
- int w = v[0].size();
- vector<vector<int> > res(h, vector<int>(w/2));
- for(int i=0;i<h;i++)
- for(int j=0;j<w/2;j++)
- res[i][j] = v[i][j] + v[i][w-1-j];
- return res;
- }
- void print_matrix(vector<vector<int> > v)
- {
- int h = v.size();
- int w = v[0].size();
- puts("=====================");
- for(int i=0;i<h;i++)
- {
- for(int j=0;j<w;j++)
- {
- if(j) putchar(' ');
- printf("%3d", v[i][j]);
- }
- puts("");
- }
- puts("=====================");
- }
- struct Matrix
- {
- int n,m;
- ll a00;
- ll dr, dc;
- Matrix(int n=0, int m=0, ll a00=0, ll dr=0, ll dc=0):
- n(n),
- m(m),
- a00(a00),
- dr(dr),
- dc(dc)
- {
- }
- Matrix vertical_fold() const
- {
- return Matrix(
- n/2,
- m,
- a00 + (a00+dr*(n-1)),
- 0,
- 2*dc
- );
- }
- Matrix horizontal_fold() const
- {
- return Matrix(
- n,
- m/2,
- a00 + (a00+dc*(m-1)),
- 2*dr,
- 0
- );
- }
- };
- struct Range
- {
- ll l, r, step;
- Range(ll l=0, ll r=0, ll step=0):
- l(l),
- r(r),
- step(step)
- {}
- };
- ll solve(int n, int m)
- {
- Matrix mtr = Matrix(n, m, 1, m, 1);
- vector<Range> ranges;
- ranges.push_back( Range(1, n*m, 1) );
- ll res = n*m;
- // assert(n*m<=(1<<16));
- // set<int> used;
- // for(int i=0;i<n;i++)
- // for(int j=0;j<m;j++)
- // used.insert(mtr.a00 + i * mtr.dr + j * mtr.dc);
- // assert(res == used.size());
- while ( mtr.n * mtr.m != 1 )
- {
- if(mtr.n >= mtr.m)
- mtr = mtr.vertical_fold();
- else
- mtr = mtr.horizontal_fold();
- if(mtr.dr*(mtr.n-1) == 0 && mtr.dc*(mtr.m-1) == 0)
- res++;
- else
- {
- Range r;
- if(mtr.dr == 0)
- r=Range(mtr.a00, mtr.a00+mtr.dc*(mtr.m-1), mtr.dc);
- else
- r=Range(mtr.a00, mtr.a00+mtr.dr*(mtr.n-1), mtr.dr);
- ll lb = r.l;
- ll rb = r.r;
- ll st = r.step;
- for(Range range: ranges)
- {
- ll cl = range.l;
- ll cr = range.r;
- ll s2 = range.step;
- assert(cl <= lb);
- assert(cr <= rb);
- if((lb-cl)%s2 != 0) continue;
- ll k = (lb-cl)/s2 % (st/s2) ;
- cl += k*s2;
- assert(cl%st == lb % st);
- k = (rb-cr)/s2 % (st/s2) ;
- cr += k*s2;
- if(k>0)
- cr -= st;
- if(cl<=cr)
- {
- assert( (cr < lb) || (cl<=lb && cr<=rb) );
- if(cr>=lb)
- lb = cr+st;
- }
- }
- if(lb<=rb)
- res+= (rb-lb+st)/st;
- ranges.push_back(r);
- // for(int i=0;i<n;i++)
- // for(int j=0;j<m;j++)
- // used.insert(mtr.a00 + i * mtr.dr + j * mtr.dc);
- // assert(res == used.size());
- }
- }
- return res;
- }
- int main()
- {
- // for(int i=0;i<=8;i++)
- // for(int j=0;i+j<=8;j++)
- // printf("%d %d %lld\n", 1<<i, 1<<j, solve(1<<i,1<<j));
- int n,m;
- scanf("%d%d",&n,&m);
- printf("%lld\n", solve(n,m));
- // vector<vector<int> > v(n, vector<int> (m));
- // for(int i=0;i<n;i++)
- // for(int j=0;j<m;j++)
- // v[i][j] = i*m+j+1;
- //
- // print_matrix(v);
- // while(v.size() * v[0].size()>1)
- // {
- // if( v.size() >= v[0].size() )
- // v = horizontal_fold(v);
- // else
- // v = vertical_fold(v);
- // print_matrix(v);
- // }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment