[ソリューション]•ジェーン・ガーデン

説明[タイトル]

ポータル

\(Lの\)は、環状の庭、時計回りの庭園、花壇があり、彼のそれぞれの番号が\(1 \) \(N(2 <= N <= 10 ^ 15)\) 彼のリング状の庭園は、毎日新しいパターンを変更しますが、彼は庭園がルール以外の何物でも、任意の隣接しているんです\(M(2 \ルM \ル5、M \ルN)\) より花壇これ以上\(K(1 \ルK <M)\) A \(C \)成形庭、花畑休止される\(P \)形状の花壇。

有効な要求スキームの数、悪い金型の数\(1E9 + 7 \)を法。

[分析]

参照してください\(M \)は、国家のプレス考慮に入れるのは簡単なので、小さいです。

しかし、見て\(N \)は、その高速電力バーとても大きいです、この質問を完了する。

【コード】

#include<cstdio>
#include<cstdlib>
#include<cstring>
#define ll long long
#define debug() puts("FBI WARNING!")
using namespace std;
const int P = 19260817;
const int MOD = 1000000007;
const int MAX = 300000 + 5; 
const int M = 5;
inline ll read(){
    ll f = 1, x = 0; char ch;
    do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0' || ch > '9');
    do {x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); } while (ch >= '0' && ch <= '9'); 
    return f * x;
}

struct TOOL {
    #define Hanabi ll
    inline Hanabi max(Hanabi a, Hanabi b) { return a < b ? b : a; }
    inline Hanabi min(Hanabi a, Hanabi b) { return a < b ? a : b; }
    inline Hanabi abs(Hanabi a) { return a < 0 ? a : a; }
}t;

int m, K, jd[1 << M], limit, cover;
ll n, f[1 << M], vis[1 << M][1 << M], ans;

inline void mul() {
    ll c[1 << M];
    memset(c, 0, sizeof c);
    for (int j = 0;j < limit; ++j) {
        for (int k = 0;k < limit; ++k) {
            c[j] = (c[j] + f[k] * vis[k][j]) % MOD;
        }
    }
    memmove(f, c, sizeof c);
}

inline void mulself() {
    ll c[1 << M][1 << M];
    memset(c, 0, sizeof c);
    for (int i = 0;i < limit; ++i) {
        for (int j = 0;j < limit; ++j) {
            for (int k = 0;k < limit; ++k) {
                c[i][j] = (c[i][j] + vis[i][k] * vis[k][j]) % MOD;
            }
        }
    }
    memmove(vis, c, sizeof c);
}

int main(){
    n = read(), m = read(), K = read();
    limit = 1 << m;
    cover = (1 << (m - 1)) - 1;
    for (int i = 0;i < limit; ++i) {
        int cnt = 0;
        for (int j = 0;j < m; ++j) {
            if (i & (1 << j)) ++cnt;
        }
        if (cnt <= K) jd[i] = 1;
    }
    
    for (int i = 0;i < limit; ++i) {
        if (jd[i] == 0) continue;
        memset(f, 0, sizeof f);
        f[i] = 1;
        memset(vis, 0, sizeof vis);
        for (int j = 0;j < limit; ++j) {
            if (jd[j] && jd[(j & cover) << 1]) vis[j][(j & cover) << 1] = 1;
            if (jd[j] && jd[((j & cover) << 1) | 1]) vis[j][((j & cover) << 1) | 1] = 1;            
        }
        ll x = n;
        while (x) {
            if (x & 1) mul();
            mulself();
            x >>= 1;
        }
        ans = (ans + f[i]) % MOD;
    }
    printf("%lld", ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/silentEAG/p/11426625.html