結果

問題 No.578 3 x N グリッド上のサイクルのサイズ(easy)
ユーザー yosupotyosupot
提出日時 2017-10-13 23:21:29
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 2 ms / 2,000 ms
コード長 12,468 bytes
コンパイル時間 1,884 ms
コンパイル使用メモリ 133,892 KB
実行使用メモリ 4,380 KB
最終ジャッジ日時 2023-08-11 00:34:22
合計ジャッジ時間 3,845 ms
ジャッジサーバーID
(参考情報)
judge13 / judge15
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,380 KB
testcase_01 AC 2 ms
4,376 KB
testcase_02 AC 2 ms
4,376 KB
testcase_03 AC 1 ms
4,376 KB
testcase_04 AC 2 ms
4,380 KB
testcase_05 AC 2 ms
4,380 KB
testcase_06 AC 2 ms
4,380 KB
testcase_07 AC 2 ms
4,380 KB
testcase_08 AC 2 ms
4,380 KB
testcase_09 AC 1 ms
4,376 KB
testcase_10 AC 2 ms
4,376 KB
testcase_11 AC 2 ms
4,376 KB
testcase_12 AC 1 ms
4,376 KB
testcase_13 AC 2 ms
4,380 KB
testcase_14 AC 1 ms
4,380 KB
testcase_15 AC 1 ms
4,376 KB
testcase_16 AC 2 ms
4,376 KB
testcase_17 AC 2 ms
4,380 KB
testcase_18 AC 2 ms
4,376 KB
testcase_19 AC 2 ms
4,376 KB
testcase_20 AC 1 ms
4,380 KB
testcase_21 AC 2 ms
4,376 KB
testcase_22 AC 2 ms
4,376 KB
testcase_23 AC 2 ms
4,380 KB
testcase_24 AC 2 ms
4,380 KB
testcase_25 AC 2 ms
4,380 KB
testcase_26 AC 2 ms
4,376 KB
testcase_27 AC 2 ms
4,380 KB
testcase_28 AC 2 ms
4,380 KB
testcase_29 AC 1 ms
4,380 KB
testcase_30 AC 2 ms
4,376 KB
testcase_31 AC 2 ms
4,380 KB
testcase_32 AC 1 ms
4,376 KB
testcase_33 AC 2 ms
4,380 KB
testcase_34 AC 1 ms
4,380 KB
testcase_35 AC 2 ms
4,376 KB
testcase_36 AC 2 ms
4,376 KB
testcase_37 AC 2 ms
4,376 KB
testcase_38 AC 2 ms
4,376 KB
testcase_39 AC 2 ms
4,380 KB
testcase_40 AC 1 ms
4,376 KB
testcase_41 AC 2 ms
4,376 KB
testcase_42 AC 1 ms
4,376 KB
testcase_43 AC 1 ms
4,376 KB
testcase_44 AC 2 ms
4,376 KB
testcase_45 AC 2 ms
4,376 KB
testcase_46 AC 2 ms
4,380 KB
testcase_47 AC 2 ms
4,376 KB
testcase_48 AC 2 ms
4,376 KB
testcase_49 AC 2 ms
4,376 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <numeric>
#include <random>
#include <vector>
#include <array>
#include <bitset>
#include <queue>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n==0) ? 1 : 10*TEN(n-1); }
template<class T> using V = vector<T>;
template<class T> using VV = V<V<T>>;

struct rng {
    struct A {
        int n;
        const bool operator!=(A r) { return n != r.n; }
        A& operator++() { n++; return *this; }
        int operator*() { return n; }
    };
    int l, r;
    rng(int r) : l(0), r(max(0, r)) {}
    rng(int l, int r) : l(l), r(max(l, r)) {}
    A begin() { return A{l}; }
    A end() { return A{r}; }
};

//bit op
int bsr(uint x) { return 31 - __builtin_clz(x); }
int bsr(ull x) { return 63 - __builtin_clzll(x); }
int bsf(uint x) { return __builtin_ctz(x); }
int bsf(ull x) { return __builtin_ctzll(x); }


template<class T>
T pow(T x, ll n, T r) {
    while (n) {
        if (n & 1) r *= x;
        x *= x;
        n >>= 1;
    }
    return r;
}
template<class T> T pow(T x, ll n) { return pow(x, n, T(1)); }

template<uint MD>
struct ModInt {
    uint v;
    ModInt() : v{0} {}
    ModInt(ll v) : v{normS(v%MD+MD)} {}
    explicit operator bool() const {return v != 0;}
    static uint normS(uint x) {return (x<MD)?x:x-MD;};
    static ModInt make(uint x) {ModInt m; m.v = x; return m;}
    static ModInt inv(const ModInt &x) {return pow(ModInt(x), MD-2);} 
    ModInt operator+(const ModInt &r) const {return make(normS(v+r.v));}
    ModInt operator-(const ModInt &r) const {return make(normS(v+MD-r.v));}
    ModInt operator*(const ModInt &r) const {return make(ull(v)*r.v%MD);}
    ModInt operator/(const ModInt &r) const {return *this*inv(r);}
    ModInt& operator+=(const ModInt &r) {return *this=*this+r;}
    ModInt& operator-=(const ModInt &r) {return *this=*this-r;}
    ModInt& operator*=(const ModInt &r) {return *this=*this*r;}
    ModInt& operator/=(const ModInt &r) {return *this=*this/r;}
};
template<uint MD> string to_string(ModInt<MD> m) {return to_string(m.v);}
using Mint = ModInt<TEN(9)+7>;

using R = double;
struct Pc {
    R x, y;
    Pc() : x(0), y(0) {}
    Pc(R x, R y) : x(x), y(y) {}
    Pc operator+(const Pc &r) const {return Pc(x+r.x, y+r.y);}
    Pc operator-(const Pc &r) const {return Pc(x-r.x, y-r.y);}
    Pc operator*(const Pc &r) const {return Pc(x*r.x-y*r.y, x*r.y+y*r.x);}
    Pc operator*(const R &r) const {return Pc(x*r, y*r);}
    Pc& operator+=(const Pc &r) {return *this=*this+r;}
    Pc& operator-=(const Pc &r) {return *this=*this-r;}
    Pc& operator*=(const Pc &r) {return *this=*this*r;}   
    Pc& operator*=(const R &r) {return *this=*this*r;}
    static Pc polar(R r, R th) {return Pc(cos(th)*r, sin(th)*r);}
};
const R PI = 4*atan(R(1));

void fft(bool type, V<Pc> &c) {
    static V<Pc> buf[30];
    int N = int(c.size());
    int s = bsr(uint(N));
    assert(1<<s == N);
    if (!buf[s].size()) {
        buf[s] = V<Pc>(N);
        for (int i = 0; i < N; i++) {
            buf[s][i] = Pc::polar(1, i*2*PI/N);
        }
    }
    V<Pc> a = c, b(N);
    for (int i = 1; i <= s; i++) {
        int W = 1<<(s-i); //変更後の幅W
        for (int y = 0; y < N/2; y += W) {
            Pc now = buf[s][y]; if (type) now.y *= -1;
            for (int x = 0; x < W; x++) {
                auto l =       a[y<<1 | x];
                auto r = now * a[y<<1 | x | W];
                b[y | x]        = l+r;
                b[y | x | N>>1] = l-r;
            }
        }
        swap(a, b);            
    }
    c = a;
}

template<class Mint>
V<Mint> multiply(V<Mint> x, V<Mint> y) {
    constexpr int B = 3, SHIFT = 10;
    int S = x.size()+y.size()-1;
    int N = 2<<bsr(uint(S-1));
    V<Pc> a[B], b[B];
    for (int fe = 0; fe < B; fe++) {
        a[fe] = V<Pc>(N);
        b[fe] = V<Pc>(N);
        V<Pc> c(N);
        for (int i = 0; i < int(x.size()); i++) {
            c[i].x = (x[i].v >> (fe*SHIFT)) & ((1<<SHIFT)-1);
        }
        for (int i = 0; i < int(y.size()); i++) {
            c[i].y = (y[i].v >> (fe*SHIFT)) & ((1<<SHIFT)-1);
        }
        fft(false, c);
        for (int i = 0; i < N; i++) {
            c[i] *= 0.5;
        }
        for (int i = 0; i < N; i++) {
            int j = (N-i)%N;
            a[fe][i] = Pc(c[i].x+c[j].x, c[i].y-c[j].y);
            b[fe][i] = Pc(c[i].y+c[j].y, -c[i].x+c[j].x);
        }
    }
    V<Mint> z(S);
    V<Pc> c[B];
    for (int fe = 0; fe < B; fe++) {
        c[fe] = V<Pc>(N);
    }
    for (int af = 0; af < B; af++) {
        for (int bf = 0; bf < B; bf++) {
            int cf = (af+bf)%B;
            for (int i = 0; i < N; i++) {
                if (af+bf<B) {
                    c[cf][i] += a[af][i]*b[bf][i];
                } else {
                    c[cf][i] += a[af][i]*b[bf][i]*Pc(0, 1);
                }
            }
        }
    }
    for (int fe = 0; fe < B; fe++) {
        fft(true, c[fe]);
    }
    Mint base = 1;
    for (int fe = 0; fe < 2*B-1; fe++) {
        for (int i = 0; i < S; i++) {
            if (fe < B) {
                c[fe][i].x *= 1.0/N;
                z[i] += Mint(ll(round(c[fe][i].x)))*base;
            } else {       
                c[fe-B][i].y *= 1.0/N;
                z[i] += Mint(ll(round(c[fe-B][i].y)))*base;
            }
        }
        base *= 1<<SHIFT;
    }
    return z;
}

template<class D>
struct Poly {
    V<D> v;
    int size() const {return int(v.size());}
    Poly(int N = 0) : v(V<D>(N)) {}
    Poly(const V<D> &v) : v(v) {shrink();}
    Poly& shrink() {while (v.size() && !v.back()) v.pop_back(); return *this;}
    D freq(int p) const { return (p < size()) ? v[p] : D(0); }

    Poly operator+(const Poly &r) const {
        int N = size(), M = r.size();
        V<D> res(max(N, M));
        for (int i = 0; i < max(N, M); i++) res[i] = freq(i)+r.freq(i);
        return Poly(res);
    }
    Poly operator-(const Poly &r) const {
        int N = size(), M = r.size();
        V<D> res(max(N, M));
        for (int i = 0; i < max(N, M); i++) res[i] = freq(i)-r.freq(i);
        return Poly(res);
    }
    Poly operator*(const Poly &r) const {
        int N = size(), M = r.size();
        if (min(N, M) == 0) return Poly();
        assert(N+M-1 >= 0);
        V<D> res = multiply(v, r.v);
        return Poly(res);
    }
    Poly operator*(const D &r) const {
        V<D> res(size());
        for (int i = 0; i < size(); i++) res[i] = v[i]*r;
        return Poly(res);
    }
    Poly& operator+=(const Poly &r) {return *this = *this+r;}
    Poly& operator-=(const Poly &r) {return *this = *this-r;}
    Poly& operator*=(const Poly &r) {return *this = *this*r;}
    Poly& operator*=(const D &r) {return *this = *this*r;}

    Poly operator<<(const int n) const {
        assert(n >= 0);
        V<D> res(size()+n);
        for (int i = 0; i < size(); i++) {
            res[i+n] = v[i];
        }
        return Poly(res);
    }
    Poly operator>>(const int n) const {
        assert(n >= 0);
        if (size() <= n) return Poly();
        V<D> res(size()-n);
        for (int i = n; i < size(); i++) {
            res[i-n] = v[i];
        }
        return Poly(res);
    }

    // x % y
    Poly rem(const Poly &y) const {
        return *this - y * div(y);
    }
    Poly rem_inv(const Poly &y, const Poly &ny, int B) const {
        return *this - y * div_inv(ny, B);
    }
    Poly div(const Poly &y) const {
        int B = max(size(), y.size());
        return div_inv(y.inv(B), B);
    }
    Poly div_inv(const Poly &ny, int B) const {
        return (*this*ny)>>(B-1);
    }
    // this * this.inv() = x^n + r(x) (size())
    Poly strip(int n) const {
        V<D> res = v;
        res.resize(min(n, size()));
        return Poly(res);
    }
    Poly rev(int n = -1) const {
        V<D> res = v;
        if (n != -1) res.resize(n);
        reverse(begin(res), end(res));
        return Poly(res);
    }
    // f * f.inv() = x^B + r(x) (B >= n)
    Poly inv(int n) const {
        int N = size();
        assert(N >= 1);
        assert(n >= N-1);
        Poly c = rev();
        Poly d = Poly(V<D>({D(1)/c.freq(0)}));
        int i;
        for (i = 1; i+N-2 < n; i *= 2) {
            auto u = V<D>({2});
            d = (d * (Poly(V<D>{2})-c*d)).strip(2*i);
        }
        return d.rev(n+1-N);
    }
};
template<class D>
string to_string(const Poly<D> &p) {
    if (p.size() == 0) return "0";
    string s = "";
    for (int i = 0; i < p.size(); i++) {
        if (p.v[i]) {
            s += to_string(p.v[i])+"x^"+to_string(i);
            if (i != p.size()-1) s += "+";
        }
    }
    return s;
}
// x^n % mod
template<class D>
Poly<D> nth_mod(ll n, const Poly<D> &mod) {
    int B = mod.size() * 2 - 1;
    Poly<D> mod_inv = mod.inv(B);
    Poly<D> p = V<D>{Mint(1)};
    int m = (!n) ? -1 : bsr(ull(n));
    for (int i = m; i >= 0; i--) {
        if (n & (1LL<<i)) {
            // += 1
            p = (p<<1).rem_inv(mod, mod_inv, B);
        }
        if (i) {
            // *= 2
            p = (p*p).rem_inv(mod, mod_inv, B);
        }
    }
    return p;
}
template<class D>
Poly<D> berlekamp_massey(const V<D> &s) {
    int N = int(s.size());
    V<D> b = {D(-1)}, c = {D(-1)};
    D y = D(1);
    for (int ed = 1; ed <= N; ed++) {
        int L = int(c.size()), M = int(b.size());
        D x = 0;
        for (int i = 0; i < L; i++) {
            x += c[i]*s[ed-L+i];
        }
        b.push_back(0); M++;
        if (!x) {
            continue;
        }
        D freq = x/y;
        if (L < M) {
            //use b
            auto tmp = c;
            c.insert(begin(c), M-L, D(0));
            for (int i = 0; i < M; i++) {
                c[M-1-i] -= freq*b[M-1-i];
            }
            b = tmp;
            y = x;
        } else {
            //use c
            for (int i = 0; i < M; i++) {
                c[L-1-i] -= freq*b[M-1-i];
            }
        }
    }
    return Poly<D>(c);
}

using Pol = Poly<Mint>;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(20);
    V<Mint> po = {
        0,
        32,
        316,
        2292,
        14422,
        84744,
        479004,
        2638328,
        14258574,
        75940592,
        399782668,
        84795558,
        786749020,
        442043859,
        352536615,
        76576421,
        744912747,
        420315017,
        25759333,
        562730793,
        424899366,
        153177921,
        250747498,
        306910436,
        324829483,
        572545341,
        104022619,
        226237183,
        421453002,
        754280938,
        291624319,
        60437277,
        297658752,
        677142927,
        63550828,
        801541292,
        683008492,
        650348,
        519624175,
        715484025,
        724658778,
        152363657,
        280344328,
        892278238,
        206785631,
        227202296,
        788486407,
        392284243,
        927772200,
        781378846,
        881515964,
        905982211,
        674841192,
        139044658,
        711210295,
        384364637,
        137653614,
        441363040,
        812818651,
        929556368,
        494420762,
        802527485,
        700803632,
        461521718,
        152786116,
        688977792,
        48724029,
        642700933,
        15567410,
        246397043,
        859581827,
        685250826,
        120226158,
        551687712,
        987163282,
        422276494,
        570671107,
        813070470,
        429968009,
        849487586,
        453150672,
        606112895,
        921636591,
        961537190,
        68995663,
        873642098,
        377371441,
        101407285,
        187434129,
        180415383,
        920712750,
        544594592,
        402649575,
        549811430,
        619506771,
        426917748,
        274013175,
        615469131,
        800944525,
        925880089,
    };

    auto pol = Pol(po);

    auto v = berlekamp_massey(po);

//    cout << to_string(v) << endl;

    ll x;
    cin >> x;
    auto z = nth_mod(x, v);
    Mint sm = 0;
    for (int i: rng(int(v.size()))) {
        sm += po[i] * z.freq(i);
    }
//    cout << to_string(z) << endl;
    cout << sm.v << endl;
    return 0;
}
0