QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#579369 | #7775. 【模板】矩阵快速幂 | fryan | 0 | 508ms | 1033880kb | C++20 | 14.3kb | 2024-09-21 13:01:09 | 2024-09-21 13:01:11 |
Judging History
answer
#pragma GCC optimize("trapv")
#include "bits/stdc++.h"
using namespace std;
#define int int64_t
#define i128 __int128_t
#define all(x) begin(x), end(x)
#define sz(x) (int) (x).size()
using namespace std;
const int BASE_DIGITS = 9, BASE = 1000000000;
struct BigInt {
int sign; vector<int> a;
// Constructors
BigInt() : sign(1) {}
BigInt(long long v) { *this = v; }
BigInt& operator=(long long v) { sign = v < 0 ? -1 : 1; v = v < 0 ? -v : v; a.clear(); while(v > 0) {a.push_back(v % BASE); v /= BASE;} return *this; }
BigInt(const string& s) { read(s); }
// Input/Output
void read(const string& s) { sign = 1; a.clear(); int pos = 0; while(pos < (int)s.size() && (s[pos] == '-' || s[pos] == '+')) { if(s[pos] == '-') sign = -sign; pos++; } for(int i = s.size()-1; i >= pos; i -= BASE_DIGITS) {int x = 0; for(int j = max(pos, i - BASE_DIGITS + 1); j <= i; j++) x = x * 10 + s[j] - '0'; a.push_back(x);} trim(); }
friend istream& operator>>(istream &stream, BigInt &v) { string s; stream >> s; v.read(s); return stream; }
friend ostream& operator<<(ostream &stream, const BigInt &v) { if(v.sign == -1 && !v.isZero()) stream << '-'; stream << (v.a.empty() ? 0 : v.a.back()); for(int i = (int)v.a.size()-2; i >=0; --i) stream << setw(BASE_DIGITS) << setfill('0') << v.a[i]; return stream; }
// Comparison
bool operator<(const BigInt &v) const { if(sign != v.sign) return sign < v.sign; if(a.size() != v.a.size()) return a.size() * sign < v.a.size() * v.sign; for(int i = a.size()-1; i >=0; i--) if(a[i] != v.a[i]) return a[i] * sign < v.a[i] * sign; return false; }
bool operator>(const BigInt &v) const { return v < *this; }
bool operator<=(const BigInt &v) const { return !(v < *this); }
bool operator>=(const BigInt &v) const { return !(*this < v); }
bool operator==(const BigInt &v) const { return !(*this < v) && !(v < *this); }
bool operator!=(const BigInt &v) const { return *this < v || v < *this; }
friend int __compare_abs(const BigInt& x, const BigInt& y) { if(x.a.size() != y.a.size()) return x.a.size() < y.a.size() ? -1 : 1; for(int i = x.a.size()-1; i >=0; --i) if(x.a[i] != y.a[i]) return x.a[i] < y.a[i] ? -1 : 1; return 0; }
// Unary and Add/Sub
BigInt operator-() const { BigInt res = *this; if(!isZero()) res.sign = -sign; return res; }
void __internal_add(const BigInt& v) { if(a.size() < v.a.size()) a.resize(v.a.size(), 0); int carry = 0; for(int i = 0; i < max(a.size(), v.a.size()) || carry; ++i) { if(i == a.size()) a.push_back(0); a[i] += carry + (i < v.a.size() ? v.a[i] : 0); carry = a[i] >= BASE ? 1 : 0; if(carry) a[i] -= BASE; } }
void __internal_sub(const BigInt& v) { int carry = 0; for(int i = 0; i < v.a.size() || carry; ++i) { a[i] -= carry + (i < v.a.size() ? v.a[i] : 0); carry = a[i] < 0 ? 1 : 0; if(carry) a[i] += BASE; } trim(); }
BigInt operator+=(const BigInt& v) { if(sign == v.sign) { __internal_add(v); } else { if(__compare_abs(*this, v) >= 0) { __internal_sub(v); } else { BigInt vv = v; swap(*this, vv); __internal_sub(vv); } } return *this; }
BigInt operator-=(const BigInt& v) { if(sign == v.sign) { if(__compare_abs(*this, v) >= 0) { __internal_sub(v); } else { BigInt vv = v; swap(*this, vv); __internal_sub(vv); sign = -sign; } } else { __internal_add(v); } return *this; }
template<typename L, typename R>
typename enable_if<is_convertible<L, BigInt>::value && is_convertible<R, BigInt>::value && is_lvalue_reference<R&&>::value, BigInt>::type
friend operator+(L&& l, R&& r) { BigInt result(std::forward<L>(l)); result += r; return result; }
template<typename L, typename R>
typename enable_if<is_convertible<L, BigInt>::value && is_convertible<R, BigInt>::value && is_rvalue_reference<R&&>::value, BigInt>::type
friend operator+(L&& l, R&& r) { BigInt result(std::move(r)); result += l; return result; }
template<typename L, typename R>
typename enable_if<is_convertible<L, BigInt>::value && is_convertible<R, BigInt>::value, BigInt>::type
friend operator-(L&& l, R&& r) { BigInt result(std::forward<L>(l)); result -= r; return result; }
// Multiplication and Division
friend pair<BigInt, BigInt> divmod(const BigInt& a1, const BigInt& b1) { assert(b1 > 0); long long norm = BASE / (b1.a.back() + 1); BigInt a = a1.abs_val() * norm, b = b1.abs_val() * norm, q = 0, r = 0; q.a.resize(a.a.size()); for(int i = a.a.size()-1; i >=0; i--) { r *= BASE; r += a.a[i]; long long s1 = r.a.size() <= b.a.size() ? 0 : r.a[b.a.size()]; long long s2 = r.a.size() <= b.a.size()-1 ? 0 : r.a[b.a.size()-1]; long long d = (static_cast<long long>(BASE) * s1 + s2) / b.a.back(); r -= b * d; while(r < 0) { r += b; --d; } q.a[i] = d; } q.sign = a1.sign * b1.sign; r.sign = a1.sign; q.trim(); r.trim(); auto res = make_pair(q, r / norm); if(res.second < 0) res.second += b1; return res; }
BigInt operator/(const BigInt &v) const { return v < 0 ? divmod(-*this, -v).first : divmod(*this, v).first; }
BigInt operator%(const BigInt &v) const { return divmod(*this, v).second; }
void operator/=(int v) { assert(v > 0); if(static_cast<long long>(std::abs(static_cast<long long>(v))) >= BASE) { *this /= BigInt(v); return; } if(v < 0) { sign = -sign; v = -v; } int rem = 0; for(int i = a.size()-1; i >=0; --i) { long long cur = a[i] + static_cast<long long>(rem) * BASE; a[i] = cur / v; rem = cur % v; } trim(); }
BigInt operator/(int v) const { assert(v > 0); if(static_cast<long long>(std::abs(static_cast<long long>(v))) >= BASE) return *this / BigInt(v); BigInt res = *this; res /= v; return res; }
void operator/=(const BigInt &v) { *this = *this / v; }
long long operator%(long long v) const { assert(v > 0 && v < BASE); int m = 0; for(int i = a.size()-1; i >=0; --i) m = (a[i] + static_cast<long long>(m) * BASE) % v; return m * sign; }
void operator*=(int v) { if(static_cast<long long>(std::abs(static_cast<long long>(v))) >= BASE) { *this *= BigInt(v); return; } if(v < 0) { sign = -sign; v = -v; } int carry = 0; for(int i = 0; i < (int)a.size() || carry; ++i) { if(i == a.size()) a.push_back(0); long long cur = static_cast<long long>(a[i]) * v + carry; carry = cur / BASE; a[i] = cur % BASE; } trim(); }
BigInt operator*(int v) const { if(static_cast<long long>(std::abs(static_cast<long long>(v))) >= BASE) return *this * BigInt(v); BigInt res = *this; res *= v; return res; }
// Base Conversion and FFT
static vector<int> convert_base(const vector<int> &a, int old_digits, int new_digits) { vector<long long> p(max(old_digits, new_digits)+1, 1); for(int i = 1; i < p.size(); i++) p[i] = p[i-1] * 10; vector<int> res; long long cur = 0; int cur_digits = 0; for(auto num : a) { cur += num * p[cur_digits]; cur_digits += old_digits; while(cur_digits >= new_digits) { res.push_back(cur % p[new_digits]); cur /= p[new_digits]; cur_digits -= new_digits; } } res.push_back(static_cast<int>(cur)); while(!res.empty() && !res.back()) res.pop_back(); return res; }
void fft(vector<complex<double>> &x, bool invert_flag) const { int n = x.size(); for(int i =1, j=0; i<n; i++){int bit = n>>1; while(j>=bit){j-=bit; bit>>=1;} j+=bit; if(i<j) swap(x[i], x[j]); } for(int len=2; len<=n; len <<=1){ double ang = 2 * 3.14159265358979323846 / len * (invert_flag ? -1 : 1); complex<double> wlen(cos(ang), sin(ang)); for(int i=0;i<n;i+=len){ complex<double> w(1); for(int j=0; j<len/2; ++j){ complex<double> u = x[i+j], v = x[i+j+len/2] * w; x[i+j] = u + v; x[i+j+len/2] = u - v; w *= wlen; } } } if(invert_flag) for(auto &c : x) c /= n; }
void multiply_fft(const vector<int> &x, const vector<int> &y, vector<int> &res) const { vector<complex<double>> fa(x.begin(), x.end()), fb(y.begin(), y.end()); int n=1; while(n < max(x.size(), y.size())) n <<=1; n <<=1; fa.resize(n); fb.resize(n); fft(fa, false); fft(fb, false); for(int i=0;i<n;i++) fa[i] *= fb[i]; fft(fa, true); res.resize(n); long long carry=0; for(int i=0;i<n;i++) { long long t = round(fa[i].real()) + carry; carry = t / 1000; res[i] = t % 1000; } }
// Multiplication Methods
BigInt mul_simple(const BigInt &v) const { BigInt res; res.sign = sign * v.sign; res.a.resize(a.size() + v.a.size(), 0); for(int i=0;i<a.size();i++) if(a[i]) for(int j=0, carry=0; j < v.a.size() || carry; j++){ long long cur = res.a[i+j] + (static_cast<long long>(a[i]) * (j < v.a.size() ? v.a[j] : 0)) + carry; carry = cur / BASE; res.a[i+j] = cur % BASE; } res.trim(); return res; }
typedef vector<long long> vll;
static vll karatsubaMultiply(const vll &a, const vll &b) { int n=a.size(); vll res(n+n, 0); if(n <=32){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) res[i+j] += a[i] * b[j]; return res; } int k=n>>1; vll a1(a.begin(), a.begin()+k), a2(a.begin()+k, a.end()), b1(b.begin(), b.begin()+k), b2(b.begin()+k, b.end()), a1b1 = karatsubaMultiply(a1, b1), a2b2 = karatsubaMultiply(a2, b2); for(int i=0;i<k;i++) { a2[i] += a1[i]; b2[i] += b1[i]; } vll r = karatsubaMultiply(a2, b2); for(int i=0;i<r.size();i++) res[i+k] += r[i] - (i < a1b1.size() ? a1b1[i] : 0) - (i < a2b2.size() ? a2b2[i] : 0); for(int i=0;i<a1b1.size();i++) res[i] += a1b1[i]; for(int i=0;i<a2b2.size();i++) res[i+n] += a2b2[i]; return res; }
BigInt mul_karatsuba(const BigInt &v) const { vector<int> x6 = convert_base(a, BASE_DIGITS, 6), y6 = convert_base(v.a, BASE_DIGITS, 6); vll x(x6.begin(), x6.end()), y(y6.begin(), y6.end()); while(x.size() < y.size()) x.push_back(0); while(y.size() < x.size()) y.push_back(0); while(x.size() & (x.size()-1)) {x.push_back(0); y.push_back(0);} vll c = karatsubaMultiply(x, y); BigInt res; res.sign = sign * v.sign; long long carry=0; for(auto num : c) { long long cur = num + carry; res.a.push_back(cur % 1000000); carry = cur / 1000000; } res.a = convert_base(res.a, 6, BASE_DIGITS); res.trim(); return res; }
BigInt mul_fft(const BigInt& v) const { BigInt res; res.sign = sign * v.sign; multiply_fft(convert_base(a, BASE_DIGITS, 3), convert_base(v.a, BASE_DIGITS, 3), res.a); res.a = convert_base(res.a, 3, BASE_DIGITS); res.trim(); return res; }
void operator*=(const BigInt &v) { *this = *this * v; }
BigInt operator*(const BigInt &v) const { if(a.size() * v.a.size() <= 1000111) return mul_simple(v); if(a.size() > 500111 || v.a.size() > 500111) return mul_fft(v); return mul_karatsuba(v); }
// Miscellaneous
BigInt abs_val() const { BigInt res = *this; res.sign = 1; return res; }
void trim() { while(!a.empty() && !a.back()) a.pop_back(); if(a.empty()) sign = 1; }
bool isZero() const { return a.empty() || (a.size() == 1 && !a[0]); }
friend BigInt gcd(const BigInt &a, const BigInt &b) { return b.isZero() ? a : gcd(b, a % b); }
friend BigInt lcm(const BigInt &a, const BigInt &b) { return a / gcd(a, b) * b; }
friend BigInt sqrt(const BigInt &a1) { BigInt a = a1; while(a.a.empty() || a.a.size() % 2 == 1) a.a.push_back(0); int n = a.a.size(); int firstDigit = static_cast<int>(sqrt(static_cast<double>(a.a[n-1]) * BASE + a.a[n-2])); int norm = BASE / (firstDigit + 1); a *= norm; a *= norm; while(a.a.empty() || a.a.size() % 2 == 1) a.a.push_back(0); BigInt r = static_cast<long long>(a.a[n-1]) * BASE + a.a[n-2]; firstDigit = static_cast<int>(sqrt(static_cast<double>(a.a[n-1]) * BASE + a.a[n-2])); int q = firstDigit; BigInt res; for(int j = n/2-1; j >=0; j--){ while(1){ BigInt temp = (res * 2 * BigInt(BASE) + q) * q; if(!(r - temp < 0)) { r = r - temp; break; } --q; } res *= BASE; res += q; if(j > 0){ int d1 = res.a.size()+2 < r.a.size() ? r.a[res.a.size()+2] : 0, d2 = res.a.size()+1 < r.a.size() ? r.a[res.a.size()+1] : 0, d3 = res.a.size() < r.a.size() ? r.a[res.a.size()] : 0; q = ((static_cast<long long>(d1) * BASE * BASE + static_cast<long long>(d2) * BASE + d3) / (firstDigit * 2)); } } res.trim(); return res / norm; }
};
const int hv = 1e18;
BigInt b(i128 x) {
int f1 = x%hv;
BigInt r = f1;
x -= f1; x /= hv;
r += BigInt(hv)*BigInt(x);
return r;
}
std::ostream& operator<<(std::ostream& out, __int128 value) { char buffer[40], *ptr = &buffer[39]; *ptr = '\0'; bool neg = value < 0; if (neg) value = -value; do { *--ptr = '0' + (value % 10); value /= 10; } while (value); if (neg) *--ptr = '-'; return out << ptr; }
const i128 inf = 1e38;
const int mxn = 305;
const int mod = 998244353;
int n,m;
BigInt k;
int U[2*mxn],V[2*mxn],W[2*mxn]; //edges
i128 cyc[mxn][mxn];
i128 dist[mxn][mxn];
i128 d1[2*mxn*mxn][mxn];
BigInt dp[mxn*mxn][mxn];
BigInt MIN(BigInt a, BigInt b) {
if (a==BigInt(-1)) return b;
if (b==BigInt(-1)) return a;
return (a<b ? a : b);
}
void solve() {
cin>>n>>m>>k;
for (int i=0; i<m; i++) {
cin>>U[i]>>V[i]>>W[i];
--U[i]; --V[i];
}
for (int cs=0; cs<n; cs++) {
for (int i=0; i<=n; i++) {
for (int j=0; j<n; j++) {
dist[i][j] = inf;
}
}
dist[0][cs] = 0;
for (int i=1; i<=n; i++) {
for (int ne=0; ne<m; ne++) {
dist[i][V[ne]] = min(dist[i][V[ne]],dist[i-1][U[ne]]+W[ne]);
}
cyc[cs][i] = dist[i][cs];
}
}
for (int i=0; i<2*n*n+5; i++) {
for (int j=0; j<n; j++) {
d1[i][j] = inf;
}
}
d1[0][0] = 0;
for (int i=1; i<2*n*n+5; i++) {
for (int ne=0; ne<m; ne++) {
d1[i][V[ne]] = min(d1[i][V[ne]],d1[i-1][U[ne]]+W[ne]);
}
}
if (k <= BigInt(n*n*2)) {
int kv = k%((int)(1e8));
for (int i=0; i<n; i++) {
cout<<(d1[kv][i]==inf?(i128)-1:d1[kv][i])<<" ";
}
cout<<"\n";
return;
}
for (int i=0; i<=n*n+5; i++) {
for (int j=0; j<n; j++) {
dp[i][j] = -1;
}
}
for (int i=0; i<n; i++) {
i128 dd = d1[n*n][i];
if (dd==inf) continue;
for (int cl=1; cl<=n; cl++) {
if (cyc[i][cl]==inf) continue;
BigInt rem = k-BigInt(2*n*n-n);
BigInt amt = rem/cl;
int residue = rem%cl;
BigInt val = BigInt(dd)+b(cyc[i][cl])*amt;
assert(residue <= n*n+5);
dp[residue+n*n-n][i] = MIN(dp[residue+n*n-n][i], val);
}
}
for (int cd = n*n+4; cd >= 0; cd--) {
for (int ne=0; ne<m; ne++) {
if (dp[cd+1][U[ne]] == BigInt(-1)) continue;
dp[cd][V[ne]] = MIN(dp[cd][V[ne]],dp[cd+1][U[ne]]+BigInt(W[ne]));
}
}
for (int i=0; i<n; i++) {
cout<<(dp[0][i])%mod<<" ";
}
cout<<"\n";
}
signed main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
int s,t; cin>>s>>t;
while (t--) {
solve();
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Subtask #1:
score: 0
Wrong Answer
Test #1:
score: 0
Wrong Answer
time: 508ms
memory: 1033880kb
input:
1 1 100 101 899539897889989959 74 35 910832669819965536 35 85 910832669819965536 85 88 910832669819965536 88 30 910832669819965536 30 58 910832669819965536 58 60 910832669819965536 60 34 910832669819965536 34 8 910832669819965536 8 67 910832669819965536 67 89 910832669819965536 89 32 910832669819965...
output:
152498985 152498974 152498976 152499032 152498986 152498982 152498947 152499025 152499038 152498948 152499016 152498966 152498946 152498993 152498975 152498956 152499040 152498954 152498987 152498984 152498979 152499014 152498991 152498958 152498965 152498963 152498950 152499012 152499036 152499021 ...
result:
wrong answer 1st numbers differ - expected: '395495792', found: '152498985'
Subtask #2:
score: 0
Time Limit Exceeded
Test #7:
score: 0
Time Limit Exceeded
input:
2 1 300 598 8179377797889487867988994778539839593376697796496698959964978969 1 2 977880533270721156 2 1 977880533270721156 2 3 977880533270721156 3 2 977880533270721156 3 4 977880533270721156 4 3 977880533270721156 4 5 977880533270721156 5 4 977880533270721156 5 6 977880533270721156 6 5 977880533270...
output:
result:
Subtask #3:
score: 0
Skipped
Dependency #2:
0%
Subtask #4:
score: 0
Skipped
Dependency #1:
0%
Subtask #5:
score: 0
Skipped
Dependency #1:
0%
Subtask #6:
score: 0
Skipped
Dependency #3:
0%