以后每做完一场CF,解题报告都写在一起吧
暴力||二分 A - Bear and Elections
题意:有n个候选人,第一个候选人可以贿赂其他人拿到他们的票,问最少要贿赂多少张票第一个人才能赢
分析:正解竟然是暴力!没敢写暴力,卡了很久,导致这场比赛差点爆零!二分的话可以优化,但对于这题来说好像不需要。。。
收获:以后CF div2的A题果断暴力
代码(暴力):
/************************************************ * Author :Running_Time * Created Time :2015-8-30 0:40:46 * File Name :A.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 1e3 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int a[N]; int n, x; int main(void) { scanf ("%d", &n); scanf ("%d", &a[0]); n--; for (int i=1; i<=n; ++i) scanf ("%d", &a[i]); int ans = 0; while (true) { int mxi = 0; for (int i=1; i<=n; ++i) { if (a[i] >= a[mxi]) mxi = i; } if (mxi == 0) break; ans++; a[0]++; a[mxi]--; } printf ("%d ", ans); return 0; }
代码(二分):
/************************************************ * Author :Running_Time * Created Time :2015-8-30 0:40:46 * File Name :A.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 1e3 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int a[N]; int n; bool cmp(int x, int y) { return x > y; } bool check(int add) { int y = a[0] + add; for (int i=1; i<=n; ++i) { if (a[i] >= y) { if (add <= 0) return false; add -= (a[i] - (y - 1)); if (add < 0) return false; } else break; } return true; } int main(void) { scanf ("%d", &n); scanf ("%d", &a[0]); n--; for (int i=1; i<=n; ++i) scanf ("%d", &a[i]); sort (a+1, a+1+n, cmp); if (a[0] > a[1]) { puts ("0"); return 0; } int l = 0, r = 1000; while (l <= r) { int mid = (l + r) >> 1; if (check (mid)) r = mid - 1; else l = mid + 1; } printf ("%d ", l); return 0; }
暴力 B - Bear and Three Musketeers
题意:找一个三元环并且三个点的度数和-6最小
分析:三元环做过一题。这题能暴力跑过,DFS不用写。枚举边的两个端点,再找是否存在另外一个点构成三元环就可以了
收获:CF div2 B也暴力过
代码:
/************************************************ * Author :Running_Time * Created Time :2015-8-25 19:24:24 * File Name :E_topo.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; typedef pair<int, int> PII; const int N = 4e3 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int deg[N]; bool g[N][N]; vector<PII> G; int n, m; int main(void) { scanf ("%d%d", &n, &m); G.clear (); memset (g, false, sizeof (g)); memset (deg, 0, sizeof (deg)); for (int u, v, i=1; i<=m; ++i) { scanf ("%d%d", &u, &v); G.push_back (PII (u, v)); g[u][v] = true; g[v][u] = true; deg[u]++; deg[v]++; } int ans = INF; for (int i=0; i<G.size (); ++i) { int u = G[i].first, v = G[i].second; for (int j=1; j<=n; ++j) { if (g[u][j] && g[v][j]) { ans = min (ans, deg[u] + deg[v] + deg[j] - 6); } } } printf ("%d ", (ans == INF) ? -1 : ans); return 0; }
题意:给n个数字,每个数字能*2或*3(可多次),问是否能使得n个数相等
分析:要达到相等,那么每个数字除了2和3的数字外的剩余数字要相等,一个数除2或3是log级别的? 复杂度不会分析。。。
收获:其实这题很水,想到/2 /3就行了
代码:
/************************************************ * Author :Running_Time * Created Time :2015-8-30 1:42:08 * File Name :C.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 1e5 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int a[N]; int GCD(int a, int b) { return b ? GCD (b, a % b) : a; } int main(void) { int n; scanf ("%d", &n); for (int i=1; i<=n; ++i) scanf ("%d", &a[i]); bool flag = true; for (int i=1; i<=n; ++i) { while (a[i] % 2 == 0) a[i] /= 2; while (a[i] % 3 == 0) a[i] /= 3; } for (int i=1; i<n; ++i) { if (a[i] != a[i+1]) { flag = false; break; } } puts (flag ? "Yes" : "No"); return 0; }
题意:有n列高度不等的方块,每次可以将和空气(至少一面不和砖头或地面接触)接触的搬走,问要搬几次
分析:先考虑一列方块时只要搬一次。两列时,如果第二列高度大于第一列,那么搬两次,否则只搬一次。三列的情况同理
问题转换成最长连续上升序列,从前往后扫一次还有从后往前扫一次,两次取最小值,答案取最大值
代码:
/************************************************ * Author :Running_Time * Created Time :2015-8-30 16:56:38 * File Name :D.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 1e5 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int a[N], dp1[N], dp2[N]; int main(void) { int n; scanf ("%d", &n); for (int i=0; i<n; ++i) scanf ("%d", &a[i]); dp1[0] = 1; for (int i=1; i<n; ++i) dp1[i] = min (a[i], dp1[i-1] + 1); dp2[n-1] = 1; for (int i=n-2; i>=0; --i) dp2[i] = min (a[i], dp2[i+1] + 1); int ans = 0; for (int i=0; i<n; ++i) { ans = max (ans, min (dp1[i], dp2[i])); } printf ("%d ", ans); return 0; }