FahimFaisal

GridPath

Jun 1st, 2021
1,299
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.78 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. #include"map"
  4. #include"set"
  5. #include"queue"
  6. #include"cmath"
  7. #include"stack"
  8. #include"ctype.h"
  9. #include"cstdio"
  10. #include"vector"
  11. #include"cstdio"
  12. #include"cstring"
  13. #include"cstdlib"
  14. #include"string.h"
  15. #include"iostream"
  16. #include"algorithm"
  17. using namespace std;
  18. #define cs "Case "<<++casee<<": "
  19. #define csE "Case "<<++casee<<":\n"
  20. #define sf(t) scanf("%d",&t)
  21. #define sNE(n,e) scanf("%d %d",&N,&E)
  22. #define Inf 1000000000
  23. #define S_N 5000010
  24. #define size_N 10000000
  25. #define MST(a, tf) memset(a, tf, sizeof (a))
  26.  
  27. using namespace std;
  28.  
  29. /*
  30. Algorithm:
  31.  
  32. 1. Calculate the total number of paths on a (n x n) grid considering there's no trap.
  33. 2. Calculate the total number of paths that generate from (1,1) block to the trap block. (Al of these paths are invalid)
  34. 3. Calculate the total number of paths that generate from the trap block to the destination block, that is, bottom right corner (Al off these paths are invalid)
  35. 4. Note: If a trap falls within the area of another trap, we will subtract the overlapping paths to avoid double-counting!
  36. 5. Now subtract these invalid paths from total paths to get the final answer.
  37. */
  38.  
  39. typedef long long ll;
  40.  
  41. ll M = 1000000007; // 1000000007 [M is a prime number]
  42. const ll N = 2000005;
  43.  
  44. ll factorial[N];
  45.  
  46. struct Trap
  47. {
  48.     ll y, x;
  49. };
  50.  
  51. // custom sorting implementation
  52. bool compareTrap(Trap trap1, Trap trap2)
  53. {
  54.     // if y values are different, sort by minimum y values
  55.     if(trap1.y != trap2.y)
  56.         return trap1.y < trap2.y;
  57.  
  58.     // otherwise, sort by minimum x values
  59.     return trap1.x < trap2.x;
  60. }
  61.  
  62. vector<Trap> trapIndex;
  63.  
  64. // This function calculates (a^b) % M
  65. ll power(ll a, ll b)
  66. {
  67.     ll x = 1;
  68.     ll y = a;
  69.  
  70.     while (b > 0)
  71.     {
  72.         if (b % 2)
  73.         {
  74.             x = (x * y) % M;
  75.         }
  76.         y = (y * y) % M;
  77.         b /= 2;
  78.     }
  79.  
  80.     return x % M;
  81. }
  82.  
  83. ll modular_inverse(ll n)
  84. {
  85.     return power(n, M-2);
  86. }
  87.  
  88. /*
  89. Algorithm for efficient nCr calculation:
  90.  
  91. 1. Let’s say we I want to find 5C2
  92. 2. We don’t need inverse of 3 and 2
  93. 3. Instead we need the inverse of 3! = 6 and 2! = 2
  94. 4. Because nCr is equal to n! / ( r! * (n — r)! )
  95. 5. So, 5C2 is: ( 5! * inv[6] * inv[2] ) % M = ( 120 * 166666668 * 500000004 ) % M = 10
  96.  
  97. */
  98.  
  99. ll calculateNcR(ll n, ll r)
  100. {
  101.     return (factorial[n] * ((modular_inverse(factorial[r]) * modular_inverse(factorial[n - r])) % M)) % M;
  102. }
  103.  
  104. int main()
  105. {
  106.     // pre-populating factorial array up to 10^6 (% M)
  107.     factorial[0] = 1;
  108.     factorial[1] = 1;
  109.  
  110.     for (int i = 2; i < N; i++)
  111.     {
  112.         factorial[i] = factorial[i-1] * i % M;
  113.     }
  114.  
  115.     ll n, m;
  116.     cin >> n >> m;
  117.  
  118.     ll totalPathsFromStartToTrap[m];
  119.  
  120.     ll y, x;
  121.     for (int i = 0; i < m; i++)
  122.     {
  123.         cin >> y >> x;
  124.  
  125.         //maintaining trap positions in a vector
  126.         trapIndex.push_back({y, x});
  127.     }
  128.  
  129.     // sorting the grid, so that we calculate the paths for earlier trap's first
  130.     sort(trapIndex.begin(), trapIndex.end(), compareTrap);
  131.  
  132.     ll totalPaths = calculateNcR((n-1) * 2, n - 1); // counting all possible pat
  133.  
  134.     for (int i = 0; i < m; i++)
  135.     {
  136.         y = trapIndex[i].y;
  137.         x = trapIndex[i].x;
  138.  
  139.         ll maxOfXY = max(y,x); // either right or down
  140.         ll minOfXY = min(y,x); // either right or down
  141.  
  142.         ll maxMove = maxOfXY + minOfXY - 2; // subtracting the starting and trap block from the count
  143.         ll minMove = minOfXY - 1; // subtracting the trap block from the count
  144.  
  145.         totalPathsFromStartToTrap[i] = calculateNcR(maxMove, minMove);
  146.  
  147.         for (int j=0; j<i; j++)
  148.         {
  149.             ll tempY, tempX;
  150.             tempY = trapIndex[j].y;
  151.             tempX = trapIndex[j].x;
  152.  
  153.             if (tempY > y || tempX > x)
  154.             {
  155.                 continue;
  156.             }
  157.             else //overlap, so, we need to remove the double counted paths!
  158.             {
  159.                 // considering a trap as child when it falls within the range(x,y) of a bigger/mother trap
  160.                 // maximum move (right/down) form child trap to mother trap
  161.                 ll childToMotherMaxMove = max(y - tempY, x - tempX);
  162.  
  163.                 // minimum move (right/down) form child trap to mother trap
  164.                 ll childToMotherMinMove = min(y - tempY, x - tempX);
  165.  
  166.                 // counting all possible way from child trap to mother trap
  167.                 // total count of moves = childToMotherMaxMove + childToMotherMinMove (right + down)
  168.                 ll totalPathsFromChildToMother = calculateNcR(childToMotherMaxMove + childToMotherMinMove, childToMotherMinMove);
  169.  
  170.                 // updating path count by subtracting illegal path's generated by child trap
  171.                 totalPathsFromStartToTrap[i] = (totalPathsFromStartToTrap[i] - totalPathsFromStartToTrap[j] * totalPathsFromChildToMother % M) % M;
  172.             }
  173.         }
  174.  
  175.         // maximum move (right/down) form trap to destination
  176.         ll trapToDestMaxMove = n - minOfXY;
  177.  
  178.         // minimum move (right/down) form trap to destination
  179.         ll trapToDestMinMove = n - maxOfXY;
  180.  
  181.         // counting all possible way from trap to bottom right
  182.         // total count of moves = trapToDestMaxMove + trapToDestMinMove (right + down)
  183.         ll totalPathsFromTrapToDest = calculateNcR(trapToDestMaxMove + trapToDestMinMove, trapToDestMinMove);
  184.  
  185.         // subtracting illegal path's generated by a trap
  186.         totalPaths = (totalPaths - totalPathsFromStartToTrap[i] * totalPathsFromTrapToDest % M) % M;
  187.  
  188.         if (totalPaths < 0)
  189.         {
  190.             totalPaths += M;
  191.         }
  192.     }
  193.     cout<<totalPaths<<endl;
  194. }
  195.  
  196. /* Sample Test Cases:
  197.  
  198. 4 2
  199. 3 1
  200. 3 3
  201.  
  202. Output: 6
  203.  
  204. 6 1
  205. 3 3
  206.  
  207. Output: 132
  208.  
  209. 5 2
  210. 4 2
  211. 3 4
  212.  
  213. Output: 24
  214.  
  215. 5 3
  216. 4 2
  217. 3 4
  218. 5 4
  219.  
  220. Output: 1
  221.  
  222. 6 3
  223. 4 2
  224. 3 4
  225. 6 3
  226.  
  227. Output: 83
  228. */
  229.  
Advertisement
Add Comment
Please, Sign In to add comment