bzoj2476戦場行列高速電力の数

トピックポータル

https://lydsy.com/JudgeOnline/problem.php?id=2476

問題の解決策

この質問は、あなたが2333年の質問に何をしたいかを確認するために質問に直面する必要があります

まず、被検者の要件を満たすようにする(または階に)大きい凸ブロックであり、一つのブロックは、次のそれぞれは、正方形である必要があり、この最後の完全な長方形ではありません。

のは、最後の条件を無視してみましょう。

我々が左端、右端または最上段または正方形を削除した場合、周囲はちょうど削減する、見つけるのは簡単です\(2 \)を必要が次の行を削除またはその行の次の列のブロックの数よりも少ないか、行を削除することを保証するため、残念ながら、この結論は、ああ、無関係と思われます。

この制限に対処する方法を考えてみましょう。なぜ、この制限の影響はありますか?行が一つのブロックを削除している場合、そのような影響ああはありません。だから我々は唯一、右端または左端の列のみ1つのボックスを削除することを検討します。

だから、最終的には例数の同じブロックの下2行の形成-この場合にも、良い解決策である、すべて同じことから、最後の行だけの円周削減することです削除\(2 \)を

だから私たちは聞かせて\(F(I)\)円周を表す\(私は\)正方形の数を。

その後、我々がいる\(F(I)= 3F(I-1)\) 彼は状況の左端と右端のボックスが再カウントされなければならないことを指摘します。また、減算する必要が\(F(I-2)\) したがって、最終的な再帰である\(F(I)= 3F(-I 1)-f(I-2)\)

行列を促進することができます。

最後に、\(F(N)\)マイナスに結果\( - 1 \ n)の前の最後の状態の影響- 。


#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back

template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}

typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;

template<typename I> inline void read(I &x) {
    int f = 0, c;
    while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    x = c & 15;
    while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    f ? x = -x : 0;
}

const int P = 987654321;

int n;

inline int smod(int x) { return x >= P ? x - P : x; }
inline void sadd(int &x, const int &y) { x += y; x >= P ? x -= P : x; }
inline int fpow(int x, int y) {
    int ans = 1;
    for (; y; y >>= 1, x = (ll)x * x % P) if (y & 1) ans = (ll)ans * x % P;
    return ans;
}

struct Matrix {
    int a[2][2];
    
    inline Matrix() { memset(a, 0, sizeof(a)); }
    inline Matrix(const int &x) {
        memset(a, 0, sizeof(a));
        a[0][0] = a[1][1] = x;
    }
    
    inline Matrix operator * (const Matrix &b) {
        Matrix c;
        c.a[0][0] = ((ll)a[0][0] * b.a[0][0] + (ll)a[0][1] * b.a[1][0]) % P;
        c.a[0][1] = ((ll)a[0][0] * b.a[0][1] + (ll)a[0][1] * b.a[1][1]) % P;
        c.a[1][0] = ((ll)a[1][0] * b.a[0][0] + (ll)a[1][1] * b.a[1][0]) % P;
        c.a[1][1] = ((ll)a[1][0] * b.a[0][1] + (ll)a[1][1] * b.a[1][1]) % P;
        return c;
    }
} A, B;

inline Matrix fpow(Matrix x, int y) {
    Matrix ans(1);
    for (; y; y >>= 1, x = x * x) if (y & 1) ans = ans * x;
    return ans;
}

inline void work() {
    if (n & 1) return (void)puts("0");
    n >>= 1;
    if (n == 1) return (void)puts("0");
    if (n == 2) return (void)puts("1");
    if (n == 3) return (void)puts("2");
    B.a[0][0] = 2, B.a[1][0] = 1;
    A.a[0][0] = 3, A.a[0][1] = -1;
    A.a[1][0] = 1, A.a[1][1] = 0;
    B = fpow(A, n - 3) * B;
    int ans = smod(B.a[0][0] - n + 1 + P);
    printf("%d\n", ans);
}

int main() {
#ifdef hzhkk
    freopen("hkk.in", "r", stdin);
#endif
    while (read(n), n) work();
    fclose(stdin), fclose(stdout);
    return 0;
}

おすすめ

転載: www.cnblogs.com/hankeke/p/bzoj2476.html