AtCoder Beginner Contest 172 (C題字首和 + 二分,D題篩因子,E題容斥定理)
阿新 • • 發佈:2021-08-07
AB水題,
C - Tsundoku
題目描述
有兩摞書,一摞有 $n$ 本,從上至下每本需閱讀 $a_i$ 分鐘,一摞有 $m$ 本,從上至下每本需閱讀 $b_i$ 分鐘,問最多能在 $k$ 分鐘內讀多少本書。
挺明顯的字首和處理,列舉從第一摞書中讀多少本,餘下的時間用二分查詢能在第二摞書中讀多少本。
ll n, m, k, a[1 << 18], b[1 << 18]; int main() { cin.tie(nullptr)->sync_with_stdio(false); cin >> n >> m >> k; for (int i = 1; i <= n; ++i) cin >> a[i], a[i] += a[i - 1]; for (int i = 1; i <= m; ++i) cin >> b[i], b[i] += b[i - 1]; ll cnt = 0; for (ll i = 0; i <= n; ++i) if (k >= a[i]) cnt = max(cnt, upper_bound(b + 1, b + m + 1, k - a[i]) - b - 1 + i); cout << cnt; }
D - Sum of Divisors
題目描述
設 $f_{(x)}$ 為 $x$ 正因子個數,計算 $\sum\limits_{i = 1}^n i\times f_{x}$
先篩出每個數的 \(f_{(x)}\) 然後累加起來
const int N = 1e7 + 10; ll a[N], n ,cnt; int main() { cin.tie(nullptr)->sync_with_stdio(false); cin >> n; for (int i = 1; i <= n; ++i) for (int j = i; j <= n; j += i) a[j] += 1; for (int i = 1; i <= n; ++i) cnt += i * a[i]; cout << cnt; }
E - NEQ
題目描述
給出 $n,m$ 計算有多少個大小為 $n$ 的子序列 $a,b$ 滿足以下條件
1.$1 \le a_i,b_i \le m$
2.$a_i \not= a_j if\ i\not= j$
3.$b_i \not= b_j if\ i\not= j$
4.$a_i \not= b_i$
沒想出來,參考了一下其他的思路:
\[A_m^n(\sum_{i = 0}^n(-1)^iC_n^iA_{m - i}^{n - i}) \]- \(A_m^n\),\(m\) 個數排 \(n\) 個位置,即合法的 \(a\) 的個數;
- \(\sum\),對於每個合法的 \(a\) 來說,合法的 \(b\) 的個數;
- \((-1)^i\),由容斥定理;
- \(C_n^iA_{m - i}^{n - i}\) ,從 \(b\) 的 \(n\) 個位置中選 \(i\) 個位置與 \(a\) 中的數相等,餘下 \(n−i\) 個位置共有 \(m−i\) 個數可選;
- 當 \(i = 0\) ,\(C_n^iA_{m - i}^{n-i} = A_m^n\) ,即合法 \(b\) 的個數;
- 當 \(i\ge 1\) ,\(C_n^iA_{m - i}^{n-i} = A_m^n\) ,即代表對 \(a\) 來說不合法 \(b\) 的個數;
- 所以右式即用容斥原理從合法的 \(b\) 中減去對 \(a\) 來說不合法的 \(b\) 的個數。
using ll = long long;
const int N = 5e5 + 10, mod = 1e9 + 7;
ll fac[N];
ll qpow(ll a, ll b) {
ll ans = 1;
for (; b; b >>= 1, a = a * a % mod)if (b & 1) ans = ans * a % mod;
return ans;
}
void init() {
fac[0] = 1;
for (int i = 1; i < N; ++i) fac[i] = fac[i - 1] * i % mod;
}
ll inv(ll n) {return qpow(n, mod - 2);}
ll A(ll n, ll m) {return fac[n] * inv(fac[n - m]) % mod;}
ll C(ll n, ll m) {return fac[n] * inv(fac[m]) % mod * inv(fac[n - m]) % mod;}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
init();
int n, m; cin >> n >> m;
ll sum = 0;
for (int i = 0; i <= n; ++i) {
sum += qpow(-1, i) * C(n, i) * A(m - i, n - i) % mod;
sum = (sum + mod) % mod;
}
cout << A(m, n) * sum % mod;
}
The desire of his soul is the prophecy of his fate
你靈魂的慾望,是你命運的先知。