Atcoder grand 025 组合数学塔涂色 贪心走路博弈
A
略
B
题意:给你N个数(3e5) 每个数可以是0,a,b,a+b(3e5) 但是总数加起来要是定值K(18e10)
问总方法数mod 998244353
解:
把a+b的看成是一个a加上一个b的 这样从0-N枚举a的个数 判断b的个数是否合法
如果合法的话 这种情况的所有方法数就相当于在N个中选i个放a 然后再在N个中选剩下的b个放b
anser = (anser + (ncr(n, i) * ncr(n, remain / B) % mod)) % mod
/*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}}; const int mod = 998244353, gakki = 5 + 2 + 1 + 19880611 + 1e9; const int MAXN = 2e5 + 5, MAXM = 2e5 + 5, N = 3e5 + 5; int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1; inline void addedge(int u, int v) { to[++tot] = v; nxt[tot] = Head[u]; Head[u] = tot; } ll Qpow(ll a, ll b) { ll ans = 1, base = a; while (b != 0) { if (b & 1 != 0) { ans = (ans * base) % mod; } base = (base * base) % mod; b >>= 1LL; } return ans % mod; } ll Inv(ll a) { return Qpow(a, mod - 2); } ll fact[N], Invfact[N], anser = 0; ll ncr(ll n, ll r) { if (r < 0 || n < 0) { return 0; } if (n < r) { return 0; } ll a = fact[n]; a = (a * Invfact[r]) % mod; a = (a * Invfact[n - r]) % mod; return a; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); ll n, A, B, K; cin >> n >> A >> B >> K; Invfact[0] = Invfact[1] = fact[0] = fact[1] = 1; for (ll i = 2; i <= 3e5 + 1; i++) { fact[i] = (fact[i - 1] * i) % mod; Invfact[i] = Inv(fact[i]); } ll remain; for (ll i = 0; i <= n; i++) { remain = K - i * A; if (remain >= 0 && remain % B == 0 && remain / B <= n) { anser = (anser + (ncr(n, i) * ncr(n, remain / B) % mod)) % mod; } } cout << anser << endl; return 0; }
C
题意:给你一个数轴和N个线段 有两个人A,B A每次给B一个线段 要求B要走到线段的范围内 B初始在原点
A会选最优方案使得B走的距离最远 而B会选最优方案使得自己走的距离最少 问你最后B走的距离是多少
解:
A选的方案肯定是使得B在原点左右来回跑 这样使得跑的距离最大
这样我们把L从大到小排列 把R从小到大排列 如果有L>R 就说明B需要走这么长的距离来满足条件
/*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; typedef unsigned long long ull; const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}}; const int mod = 998244353, gakki = 5 + 2 + 1 + 19880611 + 1e9; const int MAXN = 2e5 + 5, MAXM = 2e5 + 5, N = 1e5 + 5; int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1; inline void addedge(int u, int v) { to[++tot] = v; nxt[tot] = Head[u]; Head[u] = tot; } vector<int> l, r; int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n; cin >> n; l.push_back(0), r.push_back(0); for (int i = 1; i <= n; i++) { int L, R; cin >> L >> R; l.push_back(L); r.push_back(R); } ll anser = 0; sort(l.rbegin(), l.rend()); sort(r.begin(), r.end()); for (int i = 0; i <= n; i++) { if (l[i] > r[i]) { anser += 2LL * (l[i] - r[i]); } } cout << anser << endl; return 0; }