結果
| 問題 |
No.1073 無限すごろく
|
| コンテスト | |
| ユーザー |
ngtkana
|
| 提出日時 | 2020-06-06 02:53:16 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 2 ms / 2,000 ms |
| コード長 | 7,872 bytes |
| コンパイル時間 | 2,164 ms |
| コンパイル使用メモリ | 203,952 KB |
| 最終ジャッジ日時 | 2025-01-10 23:11:59 |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 30 |
ソースコード
#define ENABLE_DEBUG 1
// Kana's kitchen {{{
#include<bits/stdc++.h>
#define ALL(v) std::begin(v),std::end(v)
#define LOOP(k) for(i64 ngtkana_is_a_genius=0; ngtkana_is_a_genius<(i64)k; ngtkana_is_a_genius++)
using i32 = std::int_least32_t;
using i64 = std::int_least64_t;
using u32 = std::uint_least32_t;
using u64 = std::uint_least64_t;
using usize = std::size_t;
template <class T, class U> using pair = std::pair<U, T>;
template <class T> using diag_pair = std::pair<T, T>;
template <class... Args> using tuple = std::tuple<Args...>;
template <class T> using vec = std::vector<T>;
template <class T> using numr = std::numeric_limits<T>;
#ifdef NGTKANA
#include<debug.hpp>
#else
#define DEBUG(...)(void)0
#endif
/*}}}*/
// mint{{{
template <class ModType> struct modint {
using value_type = typename ModType::value_type;
using mint = modint<ModType>;
using mod_type = ModType;
static value_type mod() { return ModType::value; }
private:
static value_type inverse(value_type x) {
value_type y=1,u=mod(),v=0;
while(x){
value_type q=u/x;
u-=q*x; std::swap(x,u);
v-=q*y; std::swap(y,v);
}
assert(x==0 && std::abs(y)==mod() && std::abs(u)==1 && std::abs(v)<mod());
return v<0?v+mod():v;
}
public:
// the member variable
value_type value;
// constructors
modint()=default;
modint(modint const&)=default;
modint(modint&&)=default;
modint& operator=(modint const&)=default;
modint& operator=(modint&&)=default;
~modint()=default;
template <class T> modint(T t) : value([t] () mutable {
if ( t <= -static_cast<T>(mod()) || static_cast<T>(mod()) <= t ) t %= mod();
return t < 0 ? t + mod() : t;
}()) {}
// operators
mint& operator+= (mint y) {
value += y.value;
if (mod() <= value) value -= mod();
return *this;
}
mint& operator-= (mint y) {
value -= y.value;
if ( value < 0 ) value += mod();
return *this;
}
mint& operator*= (mint y) {
value = (long long)value * y.value % mod();
return *this;
}
mint& operator/= (mint y) {
value = (long long)value * inverse(y.value) % mod();
return *this;
}
mint& operator++() { return *this+=1; }
mint& operator--() { return *this-=1; }
mint operator++(int) const { mint this_=*this; ++*this; return this_; }
mint operator--(int) const { mint this_=*this; --*this; return this_; }
mint operator-() const { return 0 - *this; }
// static member functions
static mint inv(mint x) { return inverse(x.value); }
static mint m1pow(long long y) { return y%2?-1:1; }
static mint pow(mint x, unsigned long long y) {
mint ans=1;
for(;y;y>>=1){
if(y&1ull) ans*=x;
x*=x;
}
return ans;
}
// non-member functions
mint& add_assign(mint y) { return *this+=y; }
mint& sub_assign(mint y) { return *this-=y; }
mint& mul_assign(mint y) { return *this*=y; }
mint& div_assign(mint y) { return *this/=y; }
mint& inv_assign() { return *this = inv(*this); }
mint& pow_assign(unsigned long long y){ return *this = pow(*this, y); }
mint add(mint y) const { mint ans=*this; return ans.add_assign(y); }
mint sub(mint y) const { mint ans=*this; return ans.sub_assign(y); }
mint mul(mint y) const { mint ans=*this; return ans.mul_assign(y); }
mint div(mint y) const { mint ans=*this; return ans.div_assign(y); }
mint inv() const { mint ans=*this; return ans.inv_assign(); }
mint pow(unsigned long long y) const { return pow(*this, y); }
mint square(mint x) const { return *this * *this; }
mint cube(mint x) const { return *this * *this * *this; }
template <class F> mint map(F const& f){
value=f(value);
return *this;
}
};
template <class T> std::istream&
operator>>(std::istream& is, modint<T>& x) {
typename modint<T>::value_type y;
is >> y;
x = modint<T>{ y };
return is;
}
template <class T> std::ostream&
operator<<(std::ostream& os, modint<T> x) {
return os << x.value;
}
template <class T> modint<T> operator+(modint<T> x, modint<T> y) { return x+=y; }
template <class T> modint<T> operator-(modint<T> x, modint<T> y) { return x-=y; }
template <class T> modint<T> operator*(modint<T> x, modint<T> y) { return x*=y; }
template <class T> modint<T> operator/(modint<T> x, modint<T> y) { return x/=y; }
template <class T> bool operator==(modint<T> x, modint<T> y) { return x.value==y.value; }
template <class T> bool operator!=(modint<T> x, modint<T> y) { return x.value!=y.value; }
template <class T, class U> modint<T> operator+(modint<T> x, U y) { return x+modint<T>(y); }
template <class T, class U> modint<T> operator-(modint<T> x, U y) { return x-modint<T>(y); }
template <class T, class U> modint<T> operator*(modint<T> x, U y) { return x*modint<T>(y); }
template <class T, class U> modint<T> operator/(modint<T> x, U y) { return x/modint<T>(y); }
template <class T, class U> bool operator==(modint<T> x, U y) { return x==modint<T>(y); }
template <class T, class U> bool operator!=(modint<T> x, U y) { return x!=modint<T>(y); }
template <class T, class U> modint<T> operator+(U x, modint<T> y) { return modint<T>(x)+y; }
template <class T, class U> modint<T> operator-(U x, modint<T> y) { return modint<T>(x)-y; }
template <class T, class U> modint<T> operator*(U x, modint<T> y) { return modint<T>(x)*y; }
template <class T, class U> modint<T> operator/(U x, modint<T> y) { return modint<T>(x)/y; }
template <class T, class U> bool operator==(U x, modint<T> y) { return modint<T>(x)==y; }
template <class T, class U> bool operator!=(U x, modint<T> y) { return modint<T>(x)!=y; }
/*}}}*/
using mint = modint<std::integral_constant<i64, 1'000'000'007>>;
template <class Mint>
class residual_polynominals {
using mint_type = Mint;
public:
vec<mint_type> f, qinv, qd;
residual_polynominals()=default;
residual_polynominals(residual_polynominals const&)=default;
residual_polynominals(residual_polynominals&&)=default;
residual_polynominals& operator=(residual_polynominals const&)=default;
residual_polynominals& operator=(residual_polynominals&&)=default;
~residual_polynominals()=default;
residual_polynominals(vec<mint> const& f_)
: f(f_)
{
assert(usize{2} <= f.size());
qinv.resize(f.size()-1), qd.resize(f.size()-1);
mint x = -f.front().inv(), y = -f.back().inv();
for (usize i=0; i<qinv.size(); i++) {
qinv.at(i) = x * f.at(i+1);
qd.at(i) = y * f.at(i);
}
}
vec<mint>& normalize(vec<mint>& a) {
while (a.size() < qd.size()) a.push_back(0);
while (qd.size() < a.size()) {
mint y = a.back(); a.pop_back();
for (usize i=0; i<qd.size(); i++) {
a.at(a.size() - qd.size() + i) += y * qd.at(i);
}
}
return a;
}
vec<mint> mul(vec<mint> a, vec<mint> b) {
normalize(a), normalize(b);
vec<mint> c(qd.size() * 2 - 1);
for (usize i=0; i<qd.size(); i++) for (usize j=0; j<qd.size(); j++) {
c.at(i+j) += a.at(i) * b.at(j);
}
return normalize(c);
}
vec<mint> pow(vec<mint> a, i64 b) {
vec<mint> ans = {1};
for(; b; a = mul(a, a), b>>=1) if (b & i64{1}) ans = mul(ans, a);
return ans;
}
};
int main() {
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
std::cout << std::setprecision(15) << std::fixed;
usize d = 6;
vec<mint> modulus(d+1, -mint::inv(d));
modulus.at(0) = 1;
residual_polynominals<mint> rp(modulus);
i64 n;
std::cin >> n;
std::cout << rp.pow(rp.qinv, n).front() << '\n';
}
ngtkana