QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#842892 | #9962. Diminishing Fractions | ucup-team5243# | TL | 1480ms | 4024kb | C++17 | 27.2kb | 2025-01-04 15:39:28 | 2025-01-04 15:39:29 |
Judging History
answer
//#ifdef NACHIA
//#define _GLIBCXX_DEBUG
//#else
//#define NDEBUG
//#endif
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using i64 = long long;
using u64 = unsigned long long;
#define rep(i,n) for(int i=0; i<int(n); i++)
const i64 INF = 1001001001001001001;
template<typename A> void chmin(A& l, const A& r){ if(r < l) l = r; }
template<typename A> void chmax(A& l, const A& r){ if(l < r) l = r; }
using namespace std;
#include <cassert>
#include <utility>
namespace nachia{
// ax + by = gcd(a,b)
// return ( x, - )
std::pair<long long, long long> ExtGcd(long long a, long long b){
long long x = 1, y = 0;
while(b){
long long u = a / b;
std::swap(a-=b*u, b);
std::swap(x-=y*u, y);
}
return std::make_pair(x, a);
}
} // namespace nachia
namespace nachia{
template<unsigned int MOD>
struct StaticModint{
private:
using u64 = unsigned long long;
unsigned int x;
public:
using my_type = StaticModint;
template< class Elem >
static Elem safe_mod(Elem x){
if(x < 0){
if(0 <= x+MOD) return x + MOD;
return MOD - ((-(x+MOD)-1) % MOD + 1);
}
return x % MOD;
}
StaticModint() : x(0){}
StaticModint(const my_type& a) : x(a.x){}
StaticModint& operator=(const my_type&) = default;
template< class Elem >
StaticModint(Elem v) : x(safe_mod(v)){}
unsigned int operator*() const noexcept { return x; }
my_type& operator+=(const my_type& r) noexcept { auto t = x + r.x; if(t >= MOD) t -= MOD; x = t; return *this; }
my_type operator+(const my_type& r) const noexcept { my_type res = *this; return res += r; }
my_type& operator-=(const my_type& r) noexcept { auto t = x + MOD - r.x; if(t >= MOD) t -= MOD; x = t; return *this; }
my_type operator-(const my_type& r) const noexcept { my_type res = *this; return res -= r; }
my_type operator-() const noexcept { my_type res = *this; res.x = ((res.x == 0) ? 0 : (MOD - res.x)); return res; }
my_type& operator*=(const my_type& r)noexcept { x = (u64)x * r.x % MOD; return *this; }
my_type operator*(const my_type& r) const noexcept { my_type res = *this; return res *= r; }
my_type pow(unsigned long long i) const noexcept {
my_type a = *this, res = 1;
while(i){ if(i & 1){ res *= a; } a *= a; i >>= 1; }
return res;
}
my_type inv() const { return my_type(ExtGcd(x, MOD).first); }
unsigned int val() const noexcept { return x; }
static constexpr unsigned int mod() { return MOD; }
static my_type raw(unsigned int val) noexcept { auto res = my_type(); res.x = val; return res; }
my_type& operator/=(const my_type& r){ return operator*=(r.inv()); }
my_type operator/(const my_type& r) const { return operator*(r.inv()); }
};
} // namespace nachia
namespace nachia{
template<unsigned int MOD>
struct PrimitiveRoot{
using u64 = unsigned long long;
static constexpr u64 powm(u64 a, u64 i) {
u64 res = 1, aa = a;
for( ; i; i /= 2){
if(i & 1) res = res * aa % MOD;
aa = aa * aa % MOD;
}
return res;
}
static constexpr bool ExamineVal(unsigned int g){
u64 t = MOD - 1;
for(u64 d=2; d*d<=t; d+=1+(d&1)) if(t % d == 0){
if(powm(g, (MOD - 1) / d) == 1) return false;
while(t % d == 0) t /= d;
}
if(t != 1) if(powm(g, (MOD - 1) / t) == 1) return false;
return true;
}
static constexpr unsigned int GetVal(){
for(u64 x=2; x<MOD; x++) if(ExamineVal(x)) return x;
return 0;
}
static const unsigned int val = GetVal();
};
} // namespace nachia
namespace nachia {
template<class mint>
struct NttInterface{
template<class Iter>
void Butterfly(Iter, int) const {}
template<class Iter>
void IButterfly(Iter, int) const {}
template<class Iter>
void BitReversal(Iter a, int N) const {
for(int i=0, j=0; j<N; j++){
if(i < j) std::swap(a[i], a[j]);
for(int k = N>>1; k > (i^=k); k>>=1);
}
}
};
} // namespace nachia
namespace nachia{
int Popcount(unsigned long long c) noexcept {
#ifdef __GNUC__
return __builtin_popcountll(c);
#else
c = (c & (~0ull/3)) + ((c >> 1) & (~0ull/3));
c = (c & (~0ull/5)) + ((c >> 2) & (~0ull/5));
c = (c & (~0ull/17)) + ((c >> 4) & (~0ull/17));
c = (c * (~0ull/257)) >> 56;
return c;
#endif
}
// please ensure x != 0
int MsbIndex(unsigned long long x) noexcept {
#ifdef __GNUC__
return 63 - __builtin_clzll(x);
#else
using u64 = unsigned long long;
int q = (x >> 32) ? 32 : 0;
auto m = x >> q;
constexpr u64 hi = 0x88888888;
constexpr u64 mi = 0x11111111;
m = (((m | ~(hi - (m & ~hi))) & hi) * mi) >> 35;
m = (((m | ~(hi - (m & ~hi))) & hi) * mi) >> 31;
q += (m & 0xf) << 2;
q += 0x3333333322221100 >> (((x >> q) & 0xf) << 2) & 0xf;
return q;
#endif
}
// please ensure x != 0
int LsbIndex(unsigned long long x) noexcept {
#ifdef __GNUC__
return __builtin_ctzll(x);
#else
return MsbIndex(x & -x);
#endif
}
}
#include <iterator>
#include <array>
namespace nachia{
template <class mint>
struct NttFromAcl : NttInterface<mint> {
using u32 = unsigned int;
using u64 = unsigned long long;
static int ceil_pow2(int n) {
int x = 0;
while ((1U << x) < (u32)(n)) x++;
return x;
}
static constexpr int bsf_constexpr(unsigned int n) {
int x = 0;
while (!(n & (1 << x))) x++;
return x;
}
struct fft_info {
static constexpr u32 g = nachia::PrimitiveRoot<mint::mod()>::val;
static constexpr int rank2 = bsf_constexpr(mint::mod()-1);
using RootTable = std::array<mint, rank2+1>;
RootTable root, iroot, rate3, irate3;
fft_info(){
root[rank2] = mint(g).pow((mint::mod() - 1) >> rank2);
iroot[rank2] = root[rank2].inv();
for(int i=rank2-1; i>=0; i--){
root[i] = root[i+1] * root[i+1];
iroot[i] = iroot[i+1] * iroot[i+1];
}
mint prod = 1, iprod = 1;
for(int i=0; i<=rank2-3; i++){
rate3[i] = root[i+3] * prod;
irate3[i] = iroot[i+3] * iprod;
prod *= iroot[i+3];
iprod *= root[i+3];
}
}
};
template<class RandomAccessIterator>
void Butterfly(RandomAccessIterator a, int n) const {
int h = ceil_pow2(n);
static const fft_info info;
int len = 0;
if((h-len)%2 == 1){
int p = 1 << (h-len-1);
for(int i=0; i<p; i++){
mint l = a[i], r = a[i+p];
a[i] = l+r; a[i+p] = l-r;
}
len++;
}
for( ; len < h; len += 2){
int p = 1 << (h-len-2);
mint rot = 1, imag = info.root[2];
u64 mod2 = u64(mint::mod()) * mint::mod();
for(int s=0; s<(1<<len); s++){
if(s) rot *= info.rate3[LsbIndex(~(u32)(s-1))];
mint rot2 = rot * rot;
mint rot3 = rot2 * rot;
int offset = (s << (h-len)) + p;
for(int i=offset-p; i<offset; i++){
u64 a0 = u64(a[i].val());
u64 a1 = u64(a[i+p].val()) * rot.val();
u64 a2 = u64(a[i+2*p].val()) * rot2.val();
u64 a3 = u64(a[i+3*p].val()) * rot3.val();
u64 a1na3imag = u64(mint(a1 + mod2 - a3).val()) * imag.val();
u64 na2 = mod2 - a2;
a[i] = a0 + a2 + a1 + a3;
a[i+1*p] = a0 + a2 + (2 * mod2 - (a1 + a3));
a[i+2*p] = a0 + na2 + a1na3imag;
a[i+3*p] = a0 + na2 + (mod2 - a1na3imag);
}
}
}
}
template<class RandomAccessIterator>
void IButterfly(RandomAccessIterator a, int n) const {
int h = ceil_pow2(n);
static const fft_info info;
constexpr int MOD = mint::mod();
int len = h;
for( ; 1 < len; len -= 2){
int p = 1 << (h-len);
mint irot = 1, iimag = info.iroot[2];
for(int s=0; s<(1<<(len-2)); s++){
if(s) irot *= info.irate3[LsbIndex(~(u32)(s-1))];
mint irot2 = irot * irot;
mint irot3 = irot2 * irot;
int offset = (s << (h-len+2)) + p;
for(int i=offset-p; i<offset; i++){
u64 a0 = a[i].val();
u64 a1 = a[i+p].val();
u64 a2 = a[i+2*p].val();
u64 a3 = a[i+3*p].val();
u64 a2na3iimag = mint((a2 + MOD - a3) * iimag.val()).val();
a[i] = a0 + a1 + a2 + a3;
a[i+p] = (a0 + (MOD - a1) + a2na3iimag) * irot.val();
a[i+2*p] = (a0 + a1 + (MOD - a2) + (MOD - a3)) * irot2.val();
a[i+3*p] = (a0 + (MOD - a1) + (MOD - a2na3iimag)) * irot3.val();
}
}
}
if(len == 1){
int p = 1 << (h-len);
for(int i=0; i<p; i++){
mint l = a[i], r = a[i+p];
a[i] = l+r; a[i+p] = l-r;
}
}
}
};
} // namespace nachia
namespace nachia {
struct BigintDecMulManager {
using Int = int;
using Arr = std::vector<Int>;
using u32 = unsigned int;
using i64 = long long;
static const Int B = 1000000000;
static const u32 MOD0 = 0x1c000001;
static const u32 MOD1 = 0x6c000001;
static const u32 MOD2 = 0x78000001;
static const u32 I0_M1 = 1540148431;
static const u32 I01_M2 = 1050399624;
static const u32 I1_M2 = 10;
static const u32 IB_M1 = 1575545083;
static const u32 IB_M2 = 65929464;
template<u32 MOD>
static std::vector<u32> convMod(int z, int n, const Arr& a, const Arr& b){
using Mint = StaticModint<MOD>;
static auto ntt = NttFromAcl<Mint>();
std::vector<Mint> a2(z);
for(int i=0; i<(int)a.size(); i++) a2[i] = a[i];
std::vector<Mint> b2(z);
for(int i=0; i<(int)b.size(); i++) b2[i] = b[i];
Mint c = Mint(z).inv();
ntt.Butterfly(a2.begin(), z);
ntt.Butterfly(b2.begin(), z);
for(int i=0; i<z; i++) a2[i] *= b2[i] * c;
ntt.IButterfly(a2.begin(), z);
std::vector<u32> res(n);
for(int i=0; i<n; i++) res[i] = a2[i].val();
return res;
}
template<u32 M>
static inline StaticModint<M> SubMod(u32 a, u32 b){
return StaticModint<M>::raw(a<b ? a+M-b : a-b);
}
static Arr BigintDecMul(const Arr& a, const Arr& b){
int n = a.size() + b.size();
int n2 = 1; while(n2 < n) n2 *= 2;
auto c0 = convMod<MOD0>(n2, n-1, a, b);
auto c1 = convMod<MOD1>(n2, n-1, a, b);
auto c2 = convMod<MOD2>(n2, n-1, a, b);
std::vector<i64> c(n+1);
using MintB = StaticModint<B>;
using Mint1 = StaticModint<MOD1>;
using Mint2 = StaticModint<MOD2>;
auto i0m1 = Mint1::raw(I0_M1);
auto i01m2 = Mint2::raw(I01_M2);
auto ibm1 = Mint1::raw(IB_M1);
auto ibm2 = Mint2::raw(IB_M2);
auto i1m2 = Mint2::raw(I1_M2);
auto m01_b = MintB::raw(MOD0) * MintB(MOD1);
for(int i=0; i<n-1; i++){
u32 d0to1 = (i0m1 * SubMod<MOD1>(c1[i], c0[i])).val();
Mint2 x01m2 = Mint2::raw(c0[i]) + Mint2::raw(MOD0) * Mint2::raw(d0to1);
MintB x01mB = MintB::raw(c0[i]) + MintB::raw(MOD0) * MintB(d0to1);
MintB xmB = x01mB + m01_b * MintB((i01m2 * SubMod<MOD2>(c2[i], x01m2.val())).val());
c[i] += xmB.val();
Mint1 y1 = SubMod<MOD1>(c1[i], xmB.val()) * ibm1;
Mint2 y2 = SubMod<MOD2>(c2[i], xmB.val()) * ibm2;
i64 y12 = (i64)y1.val() + (i64)MOD1 * (i64)(i1m2 * SubMod<MOD2>(y2.val(), y1.val())).val();
c[i+1] += y12 % B; c[i+2] += y12 / B;
}
Arr res(n);
for(int i=0; i<n; i++){
res[i] = c[i]%B;
c[i+1] += c[i]/B;
}
if(res.back() == 0) res.pop_back();
return res;
}
};
};
namespace nachia {
struct BigintDec{
using Int = int;
using Arr = std::vector<Int>;
BigintDec() : sign(0), A(0) {}
BigintDec(int z){
if(z == 0){ sign = 0; }
else if(z < 0){ sign = -1; A = Arr(1, -z); }
else{ sign = 1; A = Arr(1, z); }
}
BigintDec(const std::string& s) : sign(1) {
auto it = s.begin();
if(it != s.end()){
if(*it == '-'){ sign = -1; it++; }
else if(*it == '+'){ it++; }
}
while(it != s.end() && *it == '0') it++;
if(it == s.end()){ sign = 0; }
else {
auto f = (s.end() - it);
int e = int((f-1) / 9);
int d = int((f-1) % 9);
A.assign(e + 1, 0);
for( ; it!=s.end(); it++){
assert('0' <= *it && *it <= '9');
A[e] = A[e] * 10 + (*it - '0');
d--; if(d < 0){ d = 8; e -= 1; }
}
}
}
BigintDec operator+(const BigintDec& r) const {
if(r.isZero()) return *this;
if(isZero()) return r;
auto x = (sign == r.sign) ?
uintSum(*this, r) : uintDiff(*this, r);
x.sign *= sign;
return x;
}
BigintDec operator-() const { return raw(-sign, A); }
BigintDec operator-(const BigintDec& r) const {
if(r.isZero()) return *this;
if(isZero()) return -r;
auto x = (sign == r.sign) ?
uintDiff(*this, r) : uintSum(*this, r);
x.sign *= sign;
return x;
}
BigintDec operator*(const BigintDec& r) const {
if(isZero() || r.isZero()) return Zero();
return raw(sign * r.sign, uintMul(*this, r));
}
std::pair<BigintDec, BigintDec> divrem(const BigintDec& r) const {
assert(!r.isZero());
if(isZero() || CmpAbs(*this, r) == 1) return { Zero(), *this };
auto invr = r.invFlex(len()+1);
auto a2 = (*this * invr).shiftRight(len() + r.len() + 2);
a2.sign = sign * r.sign;
auto rem = (*this) - (r * a2);
if(CmpAbs(r, rem) >= 0){
rem = rem - r;
a2 = a2 + BigintDec("1");
}
return std::make_pair(std::move(a2), std::move(rem));
}
BigintDec operator/(const BigintDec& r){
assert(!r.isZero());
return divrem(r).first;
}
BigintDec& operator*=(int x){
if(x == 0) return (*this) = Zero();
i64 y = std::abs(x);
i64 c = 0;
for(int i=0; i<len(); i++){
c += A[i] * y;
A[i] = c % B; c /= B;
}
if(c >= B){ A.push_back(c % B); c /= B; }
if(c) A.push_back(c);
if(x < 0) sign = -sign;
return *this;
}
static BigintDec Zero(){ return BigintDec(); }
bool isZero() const { return sign == 0; }
std::string toString() const {
if(isZero()) return "0";
std::string s;
for(int i=0; i<len()-1; i++){
int a = A[i];
for(int d=0; d<9; d++){ s.push_back('0'+a%10); a /= 10; }
}
for(Int a=A[len()-1]; a!=0; a/=10) s.push_back('0'+a%10);
if(sign < 0) s.push_back('-');
std::reverse(s.begin(), s.end());
return s;
}
bool operator<(const BigintDec& r) const {
if(sign != r.sign) return sign < r.sign;
return CmpAbs(*this, r) == sign;
}
bool operator>(const BigintDec& r) const { return r < *this; }
bool operator<=(const BigintDec& r) const { return !(r < *this); }
bool operator>=(const BigintDec& r) const { return !(*this < r); }
bool operator==(const BigintDec& r) const { return sign == r.sign && A == r.A; }
bool operator!=(const BigintDec& r) const { return !(*this == r); }
private:
using Self = BigintDec;
using i64 = long long;
int sign;
std::vector<Int> A;
static const int B = 1000000000;
int len() const { return int(A.size()); }
Int dig(int z) const { return z < len() ? A[z] : 0; }
Int& operator[](int z){ return A[z]; }
const Int& operator[](int z) const { return A[z]; }
static int CmpUintPos(const Self& l, const Self& r){
if(l.len() != r.len()) return std::max(l.len(), r.len()) - 1;
for(int i=l.len()-1; i>=0; i--) if(l[i] != r[i]) return i;
return -1;
}
static int CmpAbs(const Self& l, const Self& r){
int k = CmpUintPos(l, r);
if(k < 0) return 0;
return l.dig(k) < r.dig(k) ? 1 : -1;
}
static Self raw(int sign, Arr a){
if(a.empty()) sign = 0;
while(!a.empty() && a.back() == 0) a.pop_back();
Self res; res.sign = sign; res.A = std::move(a);
return res;
}
static Self uintDiff2(const Self& l, const Self& r, int k){
Arr A(k + 1);
for(int i=0; i<=k; i++) A[i] = l[i];
int j = std::min(k+1, r.len());
Int v = 0;
for(int i=0; i<j; i++){
v = v + A[i] - r[i];
if(v < 0){ A[i] = v + B; v = -1; }
else { A[i] = v; v = 0; }
}
for(int i=j; v!=0; i++){
v = v + A[i];
if(v < 0){ A[i] = v + B; v = -1; }
else { A[i] = v; v = 0; }
}
return raw(1, std::move(A));
}
static Self uintDiff(const Self& l, const Self& r){
int k = CmpUintPos(l, r);
if(k == -1) return Zero();
if(l.dig(k) > r.dig(k)) return uintDiff2(l, r, k);
auto x = uintDiff2(r, l, k); x.sign = -x.sign;
return x;
}
static Self uintSum(const Self& l, const Self& r){
if(l.len() > r.len()) return uintSum(r, l);
Arr A(r.len() + 1);
for(int i=0; i<l.len(); i++) A[i] = l[i];
Int v = 0;
for(int i=0; i<r.len(); i++){
v = v + A[i] + r[i];
if(B <= v){ A[i] = v - B; v = 1; }
else { A[i] = v; v = 0; }
}
if(v != 0) A[r.len()] = v; else A.pop_back();
return raw(1, std::move(A));
}
static Arr uintMul(const Self& l, const Self& r){
if(l.len() >= 30 && r.len() >= 30){
return BigintDecMulManager::BigintDecMul(l.A, r.A);
}
int z = l.len() + r.len();
Arr a(z);
for(int i=0; i<l.len(); i++) for(int j=0; j<r.len(); j++){
i64 x = (i64)(l[i]) * r[j] + a[i+j];
a[i+j] = x % B; a[i+j+1] += x / B;
}
if(a.back() == 0) a.pop_back();
return a;
}
Self shiftLeft(int delta) const {
if(isZero()) return Zero();
Arr a(len() + delta);
for(int i=0; i<len(); i++) a[i+delta] = A[i];
return raw(sign, std::move(a));
}
Self shiftRight(int delta) const {
if(len() <= delta) return Zero();
Arr a(len() - delta);
for(int i=delta; i<len(); i++) a[i-delta] = A[i];
return raw(sign, std::move(a));
}
Self shiftToLength(int tg) const {
return len() < tg ? shiftLeft(tg - len())
: shiftRight(len() - tg);
}
void negate(){ sign = -sign; }
Self invFlex(int prec) const {
Int t = B / (A[len()-1] + 1);
auto a2 = *this; a2 *= t;
auto b2 = a2.invPrec(prec);
b2 *= t;
return b2;
}
Self invPrec(int prec){
if(prec == 1){
Int b = A[len()-1];
Arr a(3); a[2] = 1; a[1] = i64(B) * B / b - B;
return raw(sign, std::move(a));
}
int subp = (prec + 1) / 2;
auto b = invPrec(subp);
auto ab = (shiftToLength(prec+1) * b).shiftRight(subp+1);
auto ab2 = Self("2").shiftLeft(prec+1) - ab;
return (ab2 * b).shiftRight(subp + 1);
}
};
}
namespace {
std::istream& operator>>(std::istream& i, nachia::BigintDec& d){
std::string s; i >> s;
d = nachia::BigintDec(s);
return i;
}
std::ostream& operator<<(std::ostream& o, const nachia::BigintDec& d){
return o << d.toString();
}
}
namespace nachia{
namespace prime_sieve_explicit_internal{
std::vector<bool> isprime = { false }; // a[x] := isprime(2x+1)
void CalcIsPrime(int z){
if((int)isprime.size() *2+1 < z+1){
int new_z = isprime.size();
while(new_z*2+1 < z+1) new_z *= 2;
z = new_z-1;
isprime.resize(z+1, true);
for(int i=1; i*(i+1)*2<=z; i++) if(isprime[i]){
for(int j=i*(i+1)*2; j<=z; j+=i*2+1) isprime[j] = false;
}
}
}
std::vector<int> prime_list = {2};
int prime_list_max = 0;
void CalcPrimeList(int z){
while((int)prime_list.size() < z){
if((int)isprime.size() <= prime_list_max + 1) CalcIsPrime(prime_list_max * 2 + 10);
for(int p=prime_list_max+1; p<(int)isprime.size(); p++){
if(isprime[p]) prime_list.push_back(p*2+1);
}
prime_list_max = isprime.size() - 1;
}
}
void CalcPrimeListUntil(int z){
if(prime_list_max < z){
CalcIsPrime(z);
for(int p=prime_list_max+1; p<(int)isprime.size(); p++){
if(isprime[p]) prime_list.push_back(p*2+1);
}
prime_list_max = isprime.size() - 1;
}
}
}
bool IsprimeExplicit(int n){
using namespace prime_sieve_explicit_internal;
if(n == 2) return true;
if(n % 2 == 0) return false;
CalcIsPrime(n);
return isprime[(n-1)/2];
}
int NthPrimeExplicit(int n){
using namespace prime_sieve_explicit_internal;
CalcPrimeList(n);
return prime_list[n];
}
int PrimeCountingExplicit(int n){
using namespace prime_sieve_explicit_internal;
if(n < 2) return 0;
CalcPrimeListUntil(n);
auto res = std::upper_bound(prime_list.begin(), prime_list.end(), n) - prime_list.begin();
return (int)res;
}
// [l, r)
std::vector<bool> SegmentedSieveExplicit(long long l, long long r){
assert(0 <= l); assert(l <= r);
long long d = r - l;
if(d == 0) return {};
std::vector<bool> res(d, true);
for(long long p=2; p*p<=r; p++) if(IsprimeExplicit(p)){
long long il = (l+p-1)/p, ir = (r+p-1)/p;
if(il <= p) il = p;
for(long long i=il; i<ir; i++) res[i*p-l] = false;
}
if(l < 2) for(long long p=l; p<2 && p<r; p++) res[l-p] = false;
return res;
}
} // namespace nachia
namespace nachia{
class DynamicModSupplier{
using u64 = unsigned long long;
using Int = unsigned int;
private:
u64 imod;
Int mod;
// atcoder library
u64 reduce2(u64 z) const noexcept {
// atcoder library
#ifdef _MSC_VER
u64 x; _umul128(z, im, &x);
#else
using u128 = unsigned __int128;
u64 x = (u64)(((u128)(z)*imod) >> 64);
#endif
return z - x * mod;
}
public:
DynamicModSupplier(unsigned int MOD = 998244353) : mod(MOD) {
assert(2 <= MOD);
assert(MOD < (1u << 31));
imod = (u64)(-1) / mod + 1;
}
Int reduce(u64 z) const noexcept {
Int v = reduce2(z);
if(mod <= v) v += mod;
return v;
}
Int add(Int a, Int b) const { a += b; if(a >= mod){ a -= mod; } return a; }
Int sub(Int a, Int b) const { a -= b; if(a >= mod){ a += mod; } return a; }
Int mul(Int a, Int b) const { return reduce((u64)a * b); }
Int muladd(Int a, Int b, Int c) const { return reduce((u64)a * b + c); }
Int inv(Int a) const {
Int v = ExtGcd(a, mod).first;
return (v < mod) ? v : (v + mod);
}
Int pow(Int a, u64 i) const {
Int r = a, ans = 1;
while(i){
if(i & 1) ans = mul(ans, r);
i /= 2;
r = mul(r, r);
}
return ans;
}
Int getMod() const { return mod; }
};
} // namespace nachia
namespace nachia{
template<unsigned int IDENTIFER, class IDENTIFER2 = void>
class DynamicModint{
using Int = unsigned int;
using MyType = DynamicModint;
private:
static DynamicModSupplier _c;
Int v;
template< class Elem >
static Elem SafeMod(Elem x, Int mod){
if(x < 0){
if(0 <= x+mod) return x + mod;
return mod - ((-(x+mod)-1) % mod + 1);
}
return x % mod;
}
public:
DynamicModint() : v(0) {}
DynamicModint(const MyType& r) : v(r.v) {}
MyType& operator=(const MyType&) = default;
DynamicModint(long long x){ v = SafeMod(x, _c.getMod()); }
static MyType raw(Int _v){ MyType res; res.v = _v; return res; }
static void setMod(DynamicModSupplier sup){ _c = std::move(sup); }
MyType operator+=(MyType r){ return v = _c.add(v, r.v); }
MyType operator+(MyType r) const { return raw(_c.add(v, r.v)); }
MyType operator-=(MyType r){ return v = _c.sub(v, r.v); }
MyType operator-(MyType r) const { return raw(_c.sub(v, r.v)); }
MyType operator-() const { return raw(v ? _c.getMod()-v : 0); }
MyType operator*=(MyType r){ return v = _c.mul(v, r.v); }
MyType operator*(MyType r) const { return raw(_c.mul(v, r.v)); }
MyType operator/=(MyType r){ return v = _c.mul(v, _c.inv(r.v)); }
MyType operator/(MyType r) const { return raw(_c.mul(v, _c.inv(r.v))); }
MyType inv() const { return raw(_c.inv(v)); }
MyType pow(unsigned long long r) const { return raw(_c.pow(v, r)); }
MyType mulAdd(MyType mul, MyType add) const { return raw(_c.muladd(v, mul.v, add.v)); }
Int val() const { return v; }
Int operator*() const { return v; }
static Int mod(){ return _c.getMod(); }
};
template<unsigned int IDENTIFER, class IDENTIFER2>
DynamicModSupplier DynamicModint<IDENTIFER, IDENTIFER2>::_c;
} // namespace nachia
void testcase(){
using Int = nachia::BigintDec;
using Modint = nachia::DynamicModint<0>;
i64 N; cin >> N;
if(N == 1){
cout << "1/1\n";
return;
}
vector<i64> A;
for(i64 p=2; p<=N; p++) if(nachia::IsprimeExplicit(p)){
i64 q = p; while(q*p <= N) q *= p;
A.push_back(q);
}
N = A.size();
sort(A.begin(), A.end());
vector<int> X(N,-1), Y(N,-1);
rep(i,N-1){ X.push_back(i*2); Y.push_back(i*2+1); }
int n = X.size();
vector<Int> prod(n);
rep(i,N) prod[i] = A[i];
for(int i=N; i<n; i++) prod[i] = prod[X[i]] * prod[Y[i]];
//for(auto a : prod) cout << a << endl;
//cout << endl;
vector<Int> Z(n);
Z.back() = 1;
for(int i=n-1; i>=N; i--){
Z[X[i]] = (Z[i] * prod[Y[i]]).divrem(prod[X[i]]).second;
Z[Y[i]] = (Z[i] * prod[X[i]]).divrem(prod[Y[i]]).second;
}
//rep(i,N) cout << A[i] << " ";
//cout << endl;
vector<int> Q(N);
rep(i,N){
Modint::setMod(A[i]);
Q[i] = Modint(stoll(Z[i].toString())).inv().val();
}
//rep(i,N) cout << Q[i] << " ";
//cout << endl;
using M2 = nachia::StaticModint<998244353>;
M2 f = 0;
M2 g = 1;
rep(i,N){
auto a = M2(A[i]).inv();
f += a * M2(Q[i]);
g *= a;
}
int p = (f - g).val();
//cout << p << endl;
rep(i,N){
if(i+p>=N){
cout << (Q[i] - A[i]);
} else {
if(i) cout << "+";
cout << Q[i];
}
cout << "/";
cout << A[i];
}
cout << "\n";
}
int main(){
ios::sync_with_stdio(false); cin.tie(nullptr);
int N; cin >> N;
rep(n,N) testcase();
return 0;
}
詳細信息
Test #1:
score: 100
Accepted
time: 0ms
memory: 3836kb
input:
2 3 6
output:
1/2-1/3 2/3-1/4-2/5
result:
ok OK, t = 2
Test #2:
score: 0
Accepted
time: 0ms
memory: 3508kb
input:
1 1
output:
1/1
result:
ok OK, t = 1
Test #3:
score: 0
Accepted
time: 0ms
memory: 3528kb
input:
10 1 2 3 4 5 6 7 8 9 10
output:
1/1 1/2 1/2-1/3 1/3-1/4 2/3-1/4-2/5 2/3-1/4-2/5 2/3+1/4-1/5-5/7 1/3+2/5+1/7-7/8 4/5+5/7-5/8-8/9 4/5+5/7-5/8-8/9
result:
ok OK, t = 10
Test #4:
score: 0
Accepted
time: 1ms
memory: 3668kb
input:
54 7 20 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 3 47 81
output:
2/3+1/4-1/5-5/7 3/5+2/7+5/9-2/11-9/13-1/16-5/17-4/19 1/2 1/2-1/3 1/3-1/4 2/3-1/4-2/5 2/3-1/4-2/5 2/3+1/4-1/5-5/7 1/3+2/5+1/7-7/8 4/5+5/7-5/8-8/9 4/5+5/7-5/8-8/9 4/5+3/7+1/8-4/9-10/11 4/5+3/7+1/8-4/9-10/11 3/5+4/7-3/8-1/9-5/11-3/13 3/5+4/7-3/8-1/9-5/11-3/13 3/5+4/7-3/8-1/9-5/11-3/13 4/5+2/7+4/9-8/11-...
result:
ok OK, t = 54
Test #5:
score: 0
Accepted
time: 6ms
memory: 3812kb
input:
92 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216 219 222 225 228 231 234 237 240 243 246 249 252 255 258 261 264 267 270 273 276 279 282 28...
output:
10/11+2/13+11/17+8/19+19/23+21/25-25/27-5/29-13/31-5/32-16/37-15/41-13/43-26/47-23/49 6/11+2/13+14/17+17/19+6/23+7/25+25/27+1/29-2/31-17/32-1/37-32/41-40/43-20/47-18/49-42/53 6/11+2/13+14/17+17/19+6/23+7/25+25/27+1/29-2/31-17/32-1/37-32/41-40/43-20/47-18/49-42/53 7/11+4/13+6/17+18/19+4/23+23/25+5/27...
result:
ok OK, t = 92
Test #6:
score: 0
Accepted
time: 164ms
memory: 3964kb
input:
1000 622 149 839 472 292 345 799 941 449 15 907 494 48 430 505 66 83 97 10 548 286 644 528 249 573 860 557 932 746 262 971 157 603 715 984 333 53 916 784 649 70 768 780 64 118 616 979 466 24 2 517 774 566 419 182 222 40 169 951 830 977 383 355 770 134 973 917 3 854 31 35 825 109 945 671 536 952 888 ...
output:
7/29+21/31+28/37+15/41+25/43+41/47+4/53+18/59+51/61+50/67+18/71+66/73+47/79+77/83+82/89+85/97+90/101+11/103+66/107+76/109+28/113+95/121+2/125+16/127+91/131+34/137+23/139+7/149+129/151+75/157+8/163+20/167+11/169+70/173+138/179+40/181+130/191+120/193+14/197+107/199+102/211+108/223+144/227+128/229+137/...
result:
ok OK, t = 1000
Test #7:
score: 0
Accepted
time: 674ms
memory: 3724kb
input:
1000 1748 1741 1576 1940 1648 1825 1183 1447 1318 1277 1913 1208 1417 1388 1143 1581 1222 1904 1407 1006 1175 1218 1734 1934 1003 1704 1984 1399 1333 1840 1317 1233 1133 1232 1776 1881 1476 1712 1401 1231 1978 1964 1419 1644 1103 1498 1454 1480 1377 1352 1837 1616 1009 1413 1199 1977 1477 1579 1920 ...
output:
21/43+23/47+47/53+14/59+19/61+57/67+26/71+14/73+20/79+43/83+65/89+63/97+7/101+60/103+88/107+4/109+107/113+92/127+84/131+20/137+77/139+142/149+64/151+108/157+91/163+104/167+162/169+49/173+20/179+110/181+124/191+110/193+28/197+177/199+10/211+37/223+118/227+88/229+9/233+33/239+62/241+144/251+190/257+11...
result:
ok OK, t = 1000
Test #8:
score: 0
Accepted
time: 1480ms
memory: 4024kb
input:
1000 2107 2115 2985 2832 2564 2529 2971 2637 2666 2172 2496 2191 2465 2199 2260 2161 2402 2369 2762 2674 2734 2252 2488 2185 2652 2014 2018 2960 2313 2063 2696 2976 2457 2247 2180 2647 2907 2901 2912 2538 2512 2623 2267 2986 2348 2170 2131 2166 2563 2111 2860 2254 2462 2080 2054 2803 2397 2778 2411 ...
output:
14/47+31/53+57/59+58/61+22/67+54/71+35/73+41/79+33/83+26/89+29/97+43/101+23/103+54/107+55/109+57/113+67/127+58/131+38/137+115/139+5/149+52/151+102/157+97/163+146/167+18/169+124/173+157/179+177/181+93/191+145/193+184/197+125/199+108/211+46/223+27/227+72/229+222/233+104/239+44/241+175/251+229/257+153/...
result:
ok OK, t = 1000
Test #9:
score: -100
Time Limit Exceeded
input:
1000 3416 3784 3793 3610 3982 3174 3253 3088 3197 3926 3664 3669 3431 3821 3340 3298 3498 3627 3194 3354 3362 3512 3865 3529 3988 3973 3852 3552 3672 3282 3035 3639 3998 3090 3771 3618 3402 3139 3903 3110 3452 3947 3941 3225 3187 3283 3243 3722 3808 3491 3309 3935 3937 3259 3909 3665 3809 3390 3285 ...
output:
30/59+58/61+10/67+1/71+37/73+10/79+11/83+81/89+37/97+29/101+54/103+20/107+20/109+23/113+21/127+106/131+102/137+43/139+17/149+41/151+22/157+48/163+104/167+30/173+116/179+114/181+113/191+155/193+126/197+90/199+209/211+71/223+15/227+39/229+224/233+168/239+117/241+216/251+202/257+120/263+145/269+15/271+...