トピックへのリンク:http://acm.hdu.edu.cn/showproblem.php?pid=6591
影響を受ける2次元座標系、すべて満たす\(5 | 2X + Yの\)点は、障害物を設定されて通過することができません。今、別の携帯電話番号と、対応するプログラムナンバーに少なくともQ一点から来るそのうちの一つの点の対が与えられている(単位長さ当たりに移動することができます)
ソリューション:まず、画像のうち、限り
すべての数値は赤い点で表され、旅をすることはできません。それは見つけることができる(これは八卦のバックギャモンである)これらの図の格子点を確実にするために、いくつかの小片(図のブロックは青色で示されている)、各2つの点間の各パッチに4つに分割されています距離は赤い点によって影響されることはありません。だから我々は、モバイル・コンピューティング・ブロックの回答間のポイント変換間の移動をブロック協会点を考慮することができます。
\新しい座標として各ブロックは、ブロックに対応する赤色ドット点未満である。この問題はI、点\((2,1)\)((1,0)\)に設定され、ブロック内の各ブロックは、左上隅点\(0 \)のために提供されてもよい一方で、座標系変換順次時計回り\(1,2,3は、\)は、便利後に同じで計算され答えは移動します。
変換の完了がブロック間の移動のための座標にI \(N- \)ライン、\(m個\)プログラムの数を移動しようとして見ることができます。彼らが考えることができるように、この\(N、Mの\)は、すべてが正の数に変換した後に、変換の多くの方法があり、負であり得るので、方法であって、第1判定\(n-は\)正または負であり、負の開始点と終了点を交換することができる場合には注意することがここで、正の数に対称変換、\(m個\)とすることができる負の場合、答えは決意の\(m個\)の後、同じになるように正または負であります点の位置は、ブロックが変更される可能性の範囲内です。
その後、我々は、我々は連続的に一方向に移動する場合、移動するステップ数が代替の方向においてよりなることを見つけ、私たちは移動の同じ方向に連続的に数を最小限にする、時間の最小数は、それがあると仮定し、計算することができます。 \(のt \)連続1つの方向に行くことをするとき、我々は対角ブロック内で歩かなければならないため、プログラムは、(2 ^トンの\)番号\を掛けますので、毎回行くために2つがあるでしょう法律。ポイント私たちは別の場所に移動方向を変更するプログラムの数を考慮しなければならないに加えて、これは組み合わせの数を計算するために使用することができ、その後、我々は唯一のポイントブロックから開始点を列挙し、仕上げブロックに到達する必要があります。
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 #define N 200001 の#define LL長い長 の#define MOD 998244353 INT T、N、M、ANS、NUM、[N] F、P [N]、Q [N]、DIS [ 4 ] [ 4 ]。 構造体のポイント { int型X、Y、O。 ボイドリード(){scanf関数(" %dの%のD "、およびX&Y);} ボイド のget () { int型 TMP =((2 * X + Y)%5 + 5)%5 。 もし(tmpは== 2)0 = 0、Y = 2 。 そう であれば(TMP == 4)O = 1、X - 、Y = 2 。 他の 場合(TMP == 3)O = 2、X -は、y-- 。 そう であれば(TMP == 1)O = 3、y-- 。 他に しばらく(真の); INT tmpx =(2 * X + Y)/ 5、tmpy =(2 * Y-X)/ 5 。 X = tmpx、Y = tmpy。 } } A、B。 ボイドpretype() { fは[ 1 ] = 2 ; P [ 1 ] = Q [ 1 ] = 1 。 F [ 0 ]、P [= 0 ] = Qを[ 0 ] = 1 ; 以下のために(int型 I = 2 ; iがNを<; iは++ ) { F [I] = 2LL * [I-F 1 ]%MOD。 P [I] = 1LL * P [I- 1 ] * I%MOD。 Q [I] = 1LL *(MOD-MOD / I)* Q [MOD%I]%MOD。 } のための(INTI = 2 ; iがN <、iは++ ) Q [I] = 1LL * Q [I- 1 ] * Q [i]は%MOD。 以下のために(int型 i = 0 ; iは< 4 ; I ++ ) のための(INT J = 0 ; J < 4 ; J ++ ) DIS [I] [J] =分(ABS(IJ)、4 -abs(IJ )) ; } INT C(INT N、int型 M){ 戻り 1LL *をP [N] * Q [m]は%MOD * Q [nm]の%MOD;} ボイド RUA(INT O1、INT O2、int型のn、int型M) { int値 W [ 2 ] = {N、M}。 INT RES = 0、TOT = 1 、T。 もし(W [O1] < 1 || [O 2] <W 1)のリターン; もし(O1、O2 == && W [O1] < 2 && N + M> 1)のリターン; RESが =(N + M)* 2 - 1 。 もし(N + M> 1 ) { W [O1] - 、W [O2] - 。 もし(O1 == O2) { T = ABS(W [O1] + 1 -w [O1 ^ 1 ])。 RES + = T、TOT = F [T]。 もし(W [O1] + 1 > = W [O1 ^ 1 ]) TOT = 1LL * TOT * C(W [O1] + 1、W [O1 ^ 1 ])%MOD。 他 TOT = 1LL * TOT * C(W [O1 ^ 1 ] - 1、[O1] W)%MOD。 } 他 { T = ABS([O1] W - W [O2])。 RES + = T、TOT = F [T]。 もし(W [O1]> = W [O2]) TOT1LL *全て* = C(W [W1] [O2] W)%MOD。 他のすべての1LL *全て* = C%([W1] W [O2] w)のMOD。 } } T = DIS [W1] [青]。 何 + = T; もし(T> 1)全て2LL * =%全MOD。 T = DIS [O2 + 2 ] [ボー]。 何 + = T; もし(T> 1)全て2LL * =%全MOD。 もし(解像度==年)NUM =(NUM +すべて)%MOD。 もし(RES <ANS)ANS =何もNUM = すべて; } のInt メイン() { pretype()。 scanf関数(" %のD "、&T)。 一方、(T-- ) { A.read()、A。取得(); B.read()、B。取得(); N =、M-Ayのことで= Bx- アックス。 もし(N == 0 && m個の== 0 ) { ANS = DIS [青] [ボー]。 NUM = ANS> 1?2:1 。 printf(" %D%D \ n " 、ANS、NUM)。 続け; } 場合(N < 0|| (N == 0 && M < 0 )) スワップ(A、B)、N = -n、M = - M。 もし(M < 0)アオ=(4 -AO)%4、ボー=(4 -Bo)%4、M = - M。 ANS = 19260817、NUM = 0 。 以下のために(int型 i = 0 ; iは< 2 I ++; ) のための(INT J = 2、J < 4 ; J ++ ) RUA(I、J - 2、N、M); printf(" %D%D \ n " 、ANS、NUM)。 } }