九月题目泛做总结。
Keywords Mathematics , Floyd, Transitive Closure, Bitset, Light-Heavy Decomposition
Table of Contents Keywords BZOJ 2257 瓶子和燃料 Description Proof Solution BZOJ 3629 聪明的燕姿 Description Proof Solution BZOJ 1703 奶牛排名 Description Solution Luogu P3398 仓鼠找Sugar Solution
数学是需要加强的地方, Bouvardia不要鸟其他人.
BZOJ 2257 瓶子和燃料 Description 给一些有容量的瓶子, 可以进行如下操作:
装满; 倒空; 从一瓶向另一瓶, 直到其中一个空或一个满.
最大化这些操作能得到的最小正体积.
Proof todo…
Solution 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cmath> using namespace std ;const int maxn = 1005 ;int n, k, v[maxn], lst[maxn * maxn], ptr;void divide (int x) { int lim = sqrt (x); for (int i = 1 ; i <= lim; ++i) if (!(x % i)) lst[++ptr] = i, lst[++ptr] = x / i; if (lim * lim == x) ptr--; } bool cmp (int a, int b) { return a > b; } int main () { scanf ("%d%d" , &n, &k); for (int i = 1 ; i <= n; ++i) scanf ("%d" , &v[i]); for (int i = 1 ; i <= n; ++i) divide(v[i]); sort(lst + 1 , lst + 1 + ptr, cmp); int tmp = 1 ; for (int i = 1 ; i <= ptr; ++i) { if (lst[i] == lst[i - 1 ]) tmp++; else tmp = 1 ; if (tmp >= k) { printf ("%d\n" , lst[i]); return 0 ; } } return 0 ; }
BZOJ 3629 聪明的燕姿 Description 统计约数和为 $S$ 的正整数个数.
Proof todo…
Solution 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 #include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <vector> #include <bitset> #include <vector> using namespace std ;typedef long long ll;const int maxn = 1e+5 + 5 ;int s, ans, lim;bitset <maxn> ispr; int prime[maxn >> 1 ], cnt;inline void euler () { ispr.set (); ispr.reset(1 ); for (int i = 2 ; i < maxn; ++i) { if (ispr.test(i)) prime[++cnt] = i; for (int j = 1 ; j <= cnt && i * prime[j] < maxn; ++j) { ispr.reset(i * prime[j]); if (!(i % prime[j])) break ; } } } inline int isprime (int x) { if (x < maxn) return ispr.test(x); for (int i = 1 ; i <= cnt && prime[i] * prime[i] <= x; ++i) if (!(x % prime[i])) return 0 ; return 1 ; } vector <int > vec;inline void dfs (ll del, int id, ll prod) { if (del == 1 ) { vec.push_back(prod); return ; } if (del - 1 >= prime[id] && isprime(del - 1 )) vec.push_back(prod * (del - 1 )); ll prd, sum; for (int i = id; prime[i] * prime[i] <= del; ++i) { prd = prime[i]; sum = prime[i] + 1 ; for (; sum <= del; prd *= prime[i], sum += prd) if (!(del % sum)) dfs(del / sum, i + 1 , prod * prd); } return ; } int main () { euler(); while (scanf ("%d" , &s) != EOF) { vec.clear(); dfs((ll)s, 1 , 1l l); printf ("%lu\n" , vec.size()); sort(vec.begin(), vec.end()); for (vector <int >::iterator i = vec.begin(); i != vec.end(); ++i) printf ("%d " , (*i)); if (vec.size()) putchar ('\n' ); } return 0 ; }
BZOJ 1703 奶牛排名 Description 已知一些大小关系, 求最少还要测量多少对大小关系, 可以保证能够得出所有对象两两间的大小关系.
Solution 模型转有向图, 不知道的就是两两之间互不可达的点.
跑一遍传递闭包, 剩下的统计答案.
但是! 跑不下来. 所以要Bitset优化 .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <bitset> using namespace std ;const int maxn = 1005 ;int n, m;bitset <maxn> mtr[maxn];int main () { scanf ("%d%d" , &n, &m); int x, y; for (int i = 1 ; i <= m; ++i) { scanf ("%d%d" , &x, &y); mtr[x][y] = 1 ; } for (int k = 1 ; k <= n; ++k) for (int i = 1 ; i <= n; ++i) if (mtr[i][k]) mtr[i] |= mtr[k]; int tot = 0 ; for (int i = 1 ; i <= n; ++i) for (int j = i + 1 ; j <= n; ++j) if (!mtr[i][j] && !mtr[j][i]) tot++; printf ("%d\n" , tot); return 0 ; }
Luogu P3398 仓鼠找Sugar Solution 这题比较裸, 本来不是很想写. 但是一个Trick感觉会有用.
链剖每次路径加再删除会慢, 所以每次打一个时间戳, 查区间最大值是否符合当前时间戳.
对于不好每次都修改再撤回的记录, 可以按时间戳递增地打标记, 每次取用时, 只要看是不是等于当前时间戳就好. 这样的思想在另一道题里也有体现, 会再提到.