Solution -「多校聯訓」小賣部
阿新 • • 發佈:2021-06-21
\(\mathcal{Description}\)
Link.
有 \(n\) 種物品,第 \(i\) 中有 \(a_i\) 個,單價為 \(b_i\)。共 \(q\) 次詢問,每次查詢用不超過 \(c\) 的錢購買種類在 \([l,r]\) 之中的物品,有多少種方案。強制線上;答案對 \(998244353\) 取模。
\(n\le10^4\),\(q\le5\times10^4\),\(c\le10^3\)。
\(\mathcal{Solution}\)
快速回答區間詢問,最基礎但容易被忽略的處理方式——字首和差。
考慮第 \(i\) 中物品的 OGF,顯然有
\[G_i(x)=\frac{1-x^{(a_i+1)b_i}}{1-x^{b_i}}. \]欲求答案 \(\sum_{k\le c}[x^k]\prod_{i=l}^rG_i(x)\)
順帶發現 \(G_j(x)\) 和 \(G_j^{-1}\) 長相完全一樣,所以這倆也就是換換加減號的事兒。精巧遞推一發可以做到 \(\mathcal O(nc)\) 預處理,查詢複雜度即求字首係數和,預先將 \(S_i(x)\) 或 \(S_i^{-1}(x)\) 的係數做字首和後即為求卷積的某項係數,暴力模擬,則有單次查詢複雜度 \(\mathcal O(c)\)。
\(\mathcal{Code}\)
/* Clearink */ #include <cstdio> #include <cstring> #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i ) #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i ) inline int rint() { int x = 0, s = getchar(); for ( ; s < '0' || '9' < s; s = getchar() ); for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' ); return x; } inline void wint( const int x ) { if ( 9 < x ) wint( x / 10 ); putchar( x % 10 ^ '0' ); } const int MAXN = 1e4, MAXC = 1e3, MOD = 998244353; int n, q, a[MAXN + 5], b[MAXN + 5]; int f[MAXN + 5][MAXC + 5], g[MAXN + 5][MAXC + 5]; inline void subeq( int& a, const int b ) { ( a -= b ) < 0 && ( a += MOD ); } inline int sub( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; } inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); } inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; } inline int mul( const long long a, const int b ) { return int( a * b % MOD ); } inline void init() { f[0][0] = g[0][0] = 1; rep ( i, 1, n ) { memcpy( f[i], f[i - 1], sizeof f[i] ); memcpy( g[i], g[i - 1], sizeof g[i] ); int t; rep ( j, t = b[i], MAXC ) addeq( f[i][j], f[i][j - t] ); per ( j, MAXC, t = ( a[i] + 1 ) * b[i] ) subeq( f[i][j], f[i][j - t] ); rep ( j, t = ( a[i] + 1 ) * b[i], MAXC ) addeq( g[i][j], g[i][j - t] ); per ( j, MAXC, t = b[i] ) subeq( g[i][j], g[i][j - t] ); } rep ( i, 0, n ) rep ( j, 1, MAXC ) addeq( g[i][j], g[i][j - 1] ); } int main() { freopen( "shop.in", "r", stdin ); freopen( "shop.out", "w", stdout ); n = rint(), q = rint(); rep ( i, 1, n ) a[i] = rint(), b[i] = rint(); init(); for ( int ans = 0, l, r, c; q--; ) { l = ( rint() + ans ) % n + 1, r = ( rint() + ans ) % n + 1, c = rint(); if ( l > r ) l ^= r ^= l ^= r; ans = 0; rep ( i, 0, c ) addeq( ans, mul( f[r][i], g[l - 1][c - i] ) ); wint( ans ), putchar( '\n' ); } return 0; }