AtCoder Beginning Contest 156
不会组合数学被吊打了……
题目链接:https://atcoder.jp/contests/abc156
A:
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define pb emplace_back 6 #define mp make_pair 7 #define eps 1e-8 8 #define lson (curpos<<1) 9 #define rson (curpos<<1|1) 10 /* namespace */ 11 using namespace std; 12 /* header end */ 13 14 int n, r; 15 16 int main() { 17 cin >> n >> r; 18 if (n >= 10) cout << r << endl; 19 else cout << r + 100 * (10 - n) << endl; 20 return 0; 21 }
B:
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define pb emplace_back 6 #define mp make_pair 7 #define eps 1e-8 8 #define lson (curpos<<1) 9 #define rson (curpos<<1|1) 10 /* namespace */ 11 using namespace std; 12 /* header end */ 13 14 int n, k; 15 16 int main() { 17 cin >> n >> k; 18 int ans = 0; 19 while (n) { 20 ans++; 21 n /= k; 22 } 23 cout << ans << endl; 24 return 0; 25 }
C:
注意是任意位置,所以要枚举到100
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define pb emplace_back 6 #define mp make_pair 7 #define eps 1e-8 8 #define lson (curpos<<1) 9 #define rson (curpos<<1|1) 10 /* namespace */ 11 using namespace std; 12 /* header end */ 13 14 const int maxn = 110; 15 int n, a[maxn], ans = INT_MAX; 16 17 int main() { 18 cin >> n; 19 for (int i = 1; i <= n; i++) cin >> a[i]; 20 for (int i = 1; i <= 100; i++) { 21 int tmp = 0; 22 for (int j = 1; j <= n; j++) tmp += (a[j] - i) * (a[j] - i); 23 ans = min(ans, tmp); 24 } 25 cout << ans << endl; 26 return 0; 27 }
D:
题意是有n朵互不相同的花,从中选择至少1朵组成一束花,且花的朵数不等于a或b,有多少种选法。
显然C(n,1)+C(n,2)+...+C(n,n)=2^n-1, 答案就是2^n-1-C(n,a)-C(n,b)
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define pb emplace_back 6 #define mp make_pair 7 #define eps 1e-8 8 #define lson (curpos<<1) 9 #define rson (curpos<<1|1) 10 /* namespace */ 11 using namespace std; 12 /* header end */ 13 14 const ll mod = 1e9 + 7; 15 ll n, a, b; 16 17 ll qp(ll x, ll b) { 18 ll ret = 1, base = x; 19 while (b) { 20 if (b & 1) ret = ret * base % mod; 21 base = base * base % mod; 22 b >>= 1; 23 } 24 return ret; 25 } 26 27 ll C(ll n, ll m) { 28 if (!m) return 1LL; 29 if (m == 1) return n; 30 ll ret = 1, maxx = max(m, (n - m)), minn = min(m, (n - m)); 31 for (ll i = n; i > maxx; i--) ret = ret * i % mod; 32 for (ll i = minn; i >= 1; i--) { 33 ll currInv = qp(i, mod - 2); 34 ret = ret * currInv % mod; 35 } 36 return ret; 37 } 38 39 int main() { 40 cin >> n >> a >> b; 41 ll total = (qp(2, n) % mod - 1 % mod + mod) % mod; 42 ll c1 = C(n, a) % mod, c2 = C(n, b) % mod; 43 ll ans = ((total - c1 + mod) % mod - c2 + mod) % mod; 44 cout << ans << endl; 45 return 0; 46 }
E:
题意是有n间房子,一开始每间房子里各有一个人,定义一次移动:某人从房间i走到房间j,且i不等于j。现在已知房间个数n和已经发生的移动次数k。问:房间人数的可能情况有多少种?
ans=∑ C(n, i) * C(n - 1, n - i - 1), 1<=i<=k
i的意思是选定i间空房子。由于有n个人,这n个人会形成n-1个空隙,要在这n-1个空隙里插入n-i-1个隔板来形成n-i个非空房子。
C(n - 1, n - i - 1)可以O(n)预处理出来。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define pb emplace_back 6 #define mp make_pair 7 #define eps 1e-8 8 #define lson (curpos<<1) 9 #define rson (curpos<<1|1) 10 /* namespace */ 11 using namespace std; 12 /* header end */ 13 14 const int maxn = 2e5 + 10; 15 const ll mod = 1e9 + 7; 16 ll fac[maxn + 1], inv[maxn + 1], dp[maxn + 1], n, k; 17 18 ll qp(ll x, ll y = mod - 2) { 19 ll ret = 1; 20 for (; y; y >>= 1, x = x * x % mod) 21 if (y & 1) ret = ret * x % mod; 22 return ret; 23 } 24 25 ll C(int x, int y) { 26 return fac[x] * inv[y] % mod * inv[x - y] % mod; 27 } 28 29 int main() { 30 fac[0] = fac[1] = 1; 31 for (int i = 1; i <= maxn; i++) fac[i] = fac[i - 1] * i % mod; 32 inv[maxn] = qp(fac[maxn]); 33 for (int i = maxn - 1; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1) % mod; 34 cin >> n >> k; 35 k = min(n - 1, k); 36 ll ans = 1; 37 for (int i = 1; i <= n; i++) dp[i] = C(n - 1, i - 1); 38 for (int i = 1; i <= k; i++) ans = (C(n, i) * dp[n - i] % mod + ans) % mod; 39 cout << ans << endl; 40 return 0; 41 }