皮亞諾曲線距離 2020 藍橋杯國賽


皮亞諾曲線距離 2020 藍橋杯國賽

鏈接:

題目:https://www.lanqiao.cn/courses/2786/learning/?id=131138

提交平台:https://www.lanqiao.cn/problems/1023/learning/

題目大意:

題解:

算法:遞歸

\((x_1,y_1)\)\((x_2,y_2)\) 之間的距離,那么求 \((0,0)\)\((x_1,y_1)\)\((0,0)\)\((x_2,y_2)\) ,然后做差即可。

\((0,0)\)\((x,y)\) ,可以一階一階的算。

  • 對於 k 階,那么它就有 9 個位置。

  • 然后我們對每一個位置進行分類討論,注意 \(x,y\) 都從 0 開始計算

  • 假設此時是第 \(k\) 階,那么邊長就是 \(len = 3^k\) ,如果從起點走到終點距離是 :\(cnt = 3^{2*k}/9\)

  • 如果 \(x<len/3\)

    • 如果\(y<len/3\) 說明在第一個部分,且起點位置不變,所以繼續遞歸
    • else 如果 \(y<len/3*2\) 說明在第二個部分,起點位置改變,所以 x 要進行變化,因為此時起點就變成了 \((len/3-1,len/3)\) ,所以 \((x,y)\) -> \((len/3-1-x,y-len/3)\) ,需要加上 1 這個部分的距離,也就是 \(cnt\)
    • else 就說明在第 3 部分,起點位置改變:\((0,len/3*2)\) ,所以 \((x,y)\) -> \((x,y - len/3*2)\) ,需要加上 1 2 部分的距離,也就是 \(cnt*2\)
  • else 如果 \(x<len*2/3\)

    • 如果 \(y<len/3\) 說明在第 6 部分,起點變成:\((len/3,len/3-1)\)\((x,y)\) 變成:\((x - len/3,len/3-1-y)\) ,加上 1 2 3 4 5 部分,也就是 \(cnt*5\)
    • else 如果 \(y<len*2/3\) ,說明在第 5 部分,起點變成:\((len*2/3-1,len*2/3-1)\)\((x,y)\) 變成:\((len*2/3-1-x,len*2/3-1-y)\) ,加上 1 2 3 4 部分,也就是 \(cnt*4\)
    • else 說明在第 4 部分,起點變成:\((len/3,len-1)\)\((x,y)\) 變成:\((x - len /3,len-1-y)\) ,加上 1 2 3 部分,也就是 \(cnt*3\)
  • \(x<len\)

    • 如果 \(y<len/3\) 說明在第 7 部分,起點變成 :\((len*2/3,0)\)\((x,y)\) 變成 :\((x - len*2/3,y)\) ,加上 1 2 3 4 5 6 部分,也就是 \(cnt*6\)
    • 如果 \(y<len*2/3\) ,說明在第 8 部分,起點變成:\((len - 1,len/3)\)\((x,y)\) 變成 \((len-1-x,y - len/3)\) ,加上 1 2 3 4 5 6 7 部分,也就是 \(cnt*7\)
    • 說明在第 9 部分,起點變成 \((len*2/3,len*2/3)\)\((x,y)\) 變成 \((x - len*2/3,y-len*2/3)\) ,加上 1 2 3 4 5 6 7 8 部分,也就是 \(cnt*8\)

\(k = 0\) 是停止條件。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f[200];
ll cal(int k,ll x,ll y) {
    if (k == 0) return 1;
    ll len = f[k], cnt = f[k * 2]/9;
//    printf("k = %d x = %lld y = %lld len = %lld cnt = %lld\n",k,x,y,len,cnt);
    if (x < len / 3) {
        if (y < len / 3) return cal(k - 1, x, y);
        if (y < len * 2 / 3) return cnt + cal(k - 1, len / 3 - 1 - x, y - len / 3);
        return cnt * 2 + cal(k - 1, x, y - len / 3 * 2);
    } else if (x < len * 2 / 3) {
        if (y < len / 3) return cnt * 5 + cal(k - 1, x - len / 3, len / 3 - 1 - y);
        else if (y < len * 2 / 3) return cnt * 4 + cal(k - 1, len * 2 / 3 - 1 - x, len * 2 / 3 - 1 - y);
        return cnt * 3 + cal(k - 1, x - len / 3, len - 1 - y);
    } else {
        if (y < len / 3) return cnt * 6 + cal(k - 1, x - len * 2 / 3, y);
        else if (y < len * 2 / 3) return cnt * 7 + cal(k - 1, len - 1 - x, y - len / 3);
        return cnt * 8 + cal(k - 1, x - len * 2 / 3, y - len * 2 / 3);
    }
}
int main() {
    f[0] = 1;
    for (int i = 1; i <= 39; i++) {
        f[i] = f[i - 1] * 3;
    }
    int k;
    ll x1, y1, x2, y2;
    scanf("%d%lld%lld%lld%lld", &k, &x1, &y1, &x2, &y2);
    ll ans1 = cal(k,x1,y1);
    ll ans2 = cal(k,x2,y2);
    ll ans = abs(ans1-ans2);
//    printf("%lld %lld\n", ans1,ans2);
    printf("%lld\n",ans);
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM