提出 #68641795
ソースコード 拡げる
#include <bits/stdc++.h>
//#define int long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define fr first
#define se second
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
mt19937_64 rnd(time(0));
const int N = 2e5 + 10;
template<const int T>
struct ModInt {
const static int mod = T;
int x;
ModInt(int x = 0) : x((x % mod + mod) % mod) {}
ModInt(long long x) : x(int((x % mod + mod) % mod)) {}
int val() { return x; }
ModInt operator + (const ModInt &a) const { int x0 = x + a.x; return ModInt(x0 < mod ? x0 : x0 - mod); }
ModInt operator - (const ModInt &a) const { int x0 = x - a.x; return ModInt(x0 < 0 ? x0 + mod : x0); }
ModInt operator * (const ModInt &a) const { return ModInt(1LL * x * a.x % mod); }
ModInt operator / (const ModInt &a) const { return *this * a.inv(); }
bool operator == (const ModInt &a) const { return x == a.x; };
bool operator != (const ModInt &a) const { return x != a.x; };
void operator += (const ModInt &a) { x += a.x; if (x >= mod) x -= mod; }
void operator -= (const ModInt &a) { x -= a.x; if (x < 0) x += mod; }
void operator *= (const ModInt &a) { x = 1LL * x * a.x % mod; }
void operator /= (const ModInt &a) { *this = *this / a; }
friend ModInt operator + (int y, const ModInt &a){ int x0 = y + a.x; return ModInt(x0 < mod ? x0 : x0 - mod); }
friend ModInt operator - (int y, const ModInt &a){ int x0 = y - a.x; return ModInt(x0 < 0 ? x0 + mod : x0); }
friend ModInt operator * (int y, const ModInt &a){ return ModInt(1LL * y * a.x % mod);}
friend ModInt operator / (int y, const ModInt &a){ return ModInt(y) / a;}
friend ostream &operator<<(ostream &os, const ModInt &a) { return os << a.x;}
friend istream &operator>>(istream &is, ModInt &t){return is >> t.x;}
ModInt power(int64_t n) const {
ModInt res(1), mul(x);
while(n){
if (n & 1) res *= mul;
mul *= mul;
n >>= 1;
}
return res;
}
ModInt inv() const {
int a = x, b = mod, u = 1, v = 0;
while (b) {
int t = a / b;
a -= t * b; swap(a, b);
u -= t * v; swap(u, v);
}
if (u < 0) u += mod;
return u;
}
};
constexpr int MOD = 998244353;
using Z = ModInt<MOD>;
struct Matrix{
Z a[2][2];
Matrix() {}
void init_E(){
a[0][0] = a[1][1] = 1;
a[1][0] = a[0][1] = 0;
}
Matrix operator* (const Matrix& other) const{
Matrix t; // 临时存储结果的矩阵
for(int i = 0; i < 2; i ++){
for(int j = 0; j < 2; j ++){
for(int k = 0; k < 2; k ++){
t.a[i][j] = (t.a[i][j] + a[i][k] * other.a[k][j]);
}
}
}
return t;
}
};
struct Node{
int l, r;
Matrix mat;
Node(){
mat.init_E();
}
}tr[N << 2];
struct SegTree{
#define lc p<<1
#define rc p<<1|1
void pushup(int p){
tr[p].mat = tr[lc].mat * tr[rc].mat;
}
void build(int p, int l, int r){
tr[p].l = l, tr[p].r = r;
tr[p].mat.init_E();
if(l == r) return;
int mid = l + r >> 1;
build(lc, l, mid);
build(rc, mid + 1, r);
pushup(p);
}
void update(int p, int l, int r, Matrix& mat){
if(l == tr[p].l && tr[p].r == r){
for(int i = 0; i < 2; i ++){
for(int j = 0; j < 2; j ++){
tr[p].mat.a[i][j] = mat.a[i][j];
}
}
return;
}
int mid = tr[p].l + tr[p].r >> 1;
if(l <= mid) update(lc, l, r, mat);
if(r > mid) update(rc, l, r, mat);
pushup(p);
}
};
Z qpow(Z a, int b, int p)
{
Z res = 1;
while (b){
if (b & 1) res = res * a;
b >>= 1;
a = a * a;
}
return res;
}
template<typename T>
struct Comb
{
vector<T> fact; // fact[i]存储i的阶乘
vector<T> infact; // infact[i]存储i的阶乘的逆元
explicit Comb(int n){
init(n);
}
void init(int n){
fact.resize(n + 1);
infact.resize(n + 1);
fact[0] = infact[0] = 1;
for (int i = 1; i <= n; i++){
fact[i] = fact[i - 1] * i;
}
infact[n] = qpow(fact[n], MOD - 2, MOD);
for (int i = n; i >= 1; i--){
infact[i - 1] = infact[i] * i;
}
}
T C(int a, int b){
if (a < 0 || b < 0 || a < b) return 0;
return fact[a] * infact[a - b] * infact[b];
}
T Catalan(int n){
return C(2 * n, n) * qpow(n + 1, MOD - 2, MOD);
}
};
int n, q;
int a[N];
Z fib[N];
Comb<Z> comb(4e5);
SegTree seg;
Z noadj(int n, int r){ // n: 茶壶数量 r: 咖啡数量
return comb.C(n - (r - 1), r);
}
Matrix get_f(int n, int r){
Matrix f;
// f[0][0]
f.a[0][0] = noadj(n - 1, r);
// f[0][1]
if(n == 1){
f.a[0][1] = noadj(0, r - 1);
}
else{
f.a[0][1] = noadj(n - 2, r - 1);
}
// f[1][0]
if(n == 1){
f.a[1][0] = noadj(0, r);
}
else{
f.a[1][0] = noadj(n - 2, r);
}
// f[1][1]
if(n == 1){
f.a[1][1] = 0;
}
else if(n == 2){
f.a[1][1] = noadj(0, r - 1);
}
else{
f.a[1][1] = noadj(n - 3, r - 1);
}
return f;
}
// 默认a[0]=0
void solve()
{
cin >> n >> q;
a[0] = 0;
for(int i = 1; i <= n; i ++){
a[i] = -1;
}
fib[0] = 1;
fib[1] = 2;
for(int i = 2; i <= n; i ++){
fib[i] = fib[i - 1] + fib[i - 2];
}
seg.build(1, 1, n);
set<int> S; // 维护所有非-1的位置
S.insert(0);
Matrix temp;
while(q --){
int x, val; cin >> x >> val;
if(a[x] == val){}
else if(a[x] == -1){ // -1 => 非-1
S.insert(x);
a[x] = val;
auto itl = S.lower_bound(x);
auto itr = S.upper_bound(x);
assert(itl != S.begin()); // 一定有0在
itl --;
int l = *itl;
assert(a[l] != -1);
temp = get_f(x - l, a[x] - a[l]);
seg.update(1, x, x, temp);
if(itr != S.end()){
int r = *itr;
assert(a[r] != -1);
temp = get_f(r - x, a[r] - a[x]);
seg.update(1, r, r, temp);
}
}
else{
auto itl = S.lower_bound(x);
auto itr = S.upper_bound(x);
assert(itl != S.begin()); // 一定有0在
itl --;
a[x] = val;
if(val == -1){ // 非-1 => -1
temp.init_E();
seg.update(1, x, x, temp);
if(itr != S.end()){
int l = *itl, r = *itr;
assert(a[l] != -1);
assert(a[r] != -1);
temp = get_f(r - l, a[r] - a[l]);
seg.update(1, r, r, temp);
}
S.erase(x);
}
else{ // 非-1 => 非-1
int l = *itl;
assert(a[l] != -1);
temp = get_f(x - l, a[x] - a[l]);
seg.update(1, x, x, temp);
if(itr != S.end()){
int r = *itr;
assert(a[r] != -1);
temp = get_f(r - x, a[r] - a[x]);
seg.update(1, r, r, temp);
}
}
}
int ed = *(--S.end());
// cout << "ed = " << ed << endl;
Matrix res = tr[1].mat;
// cout << res.a[0][0] << " " << res.a[0][1] << endl;
// cout << res.a[1][0] << " " << res.a[1][1] << endl;
Z ans = res.a[0][0] * fib[n - ed] + res.a[0][1] * fib[max(0, n - ed - 1)];
cout << ans << endl;
}
}
signed main()
{
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
// int T=1; cin>>T; while(T--)
solve();
return 0;
}
提出情報
提出日時
2025-08-19 23:04:31+0900
問題
F - We're teapots
ユーザ
jjjxs
言語
C++ 20 (gcc 12.2)
得点
550
コード長
7125 Byte
結果
AC
実行時間
470 ms
メモリ
30192 KiB
コンパイルエラー
Main.cpp: In member function ‘void SegTree::build(int, int, int)’:
Main.cpp:108:29: warning: suggest parentheses around ‘+’ inside ‘>>’ [-Wparentheses]
108 | int mid = l + r >> 1;
| ~~^~~
Main.cpp: In member function ‘void SegTree::update(int, int, int, Matrix&)’:
Main.cpp:123:35: warning: suggest parentheses around ‘+’ inside ‘>>’ [-Wparentheses]
123 | int mid = tr[p].l + tr[p].r >> 1;
| ~~~~~~~~^~~~~~~~~
Main.cpp: In function ‘Z qpow(Z, int, int)’:
Main.cpp:130:24: warning: unused parameter ‘p’ [-Wunused-parameter]
130 | Z qpow(Z a, int b, int p)
| ~~~~^
ジャッジ結果
セット名
Sample
All
得点 / 配点
0 / 0
550 / 550
結果
セット名
テストケース
Sample
00-sample-01.txt
All
00-sample-01.txt, 01-01.txt, 01-02.txt, 01-03.txt, 01-04.txt, 01-05.txt, 01-06.txt, 01-07.txt, 01-08.txt, 01-09.txt, 01-10.txt, 01-11.txt, 01-12.txt, 01-13.txt, 01-14.txt, 01-15.txt, 01-16.txt
ケース名
結果
実行時間
メモリ
00-sample-01.txt
AC
16 ms
25696 KiB
01-01.txt
AC
22 ms
25816 KiB
01-02.txt
AC
27 ms
25696 KiB
01-03.txt
AC
19 ms
25852 KiB
01-04.txt
AC
351 ms
26376 KiB
01-05.txt
AC
356 ms
26676 KiB
01-06.txt
AC
356 ms
26708 KiB
01-07.txt
AC
361 ms
26692 KiB
01-08.txt
AC
353 ms
29136 KiB
01-09.txt
AC
390 ms
30108 KiB
01-10.txt
AC
382 ms
30192 KiB
01-11.txt
AC
442 ms
30184 KiB
01-12.txt
AC
445 ms
30144 KiB
01-13.txt
AC
468 ms
26752 KiB
01-14.txt
AC
457 ms
26404 KiB
01-15.txt
AC
470 ms
26692 KiB
01-16.txt
AC
467 ms
26728 KiB