A:
现有两种购物方式 1.花单价a元购买 2.花c元购买b个物品 给出数据后问 1.购买多少个物品可以使得用方式1的花费严格小于方式2 2.购买多少个物品可以使得用方式2的花费严格小于方式1
若不存在输出-1
直接贪心 由于b>=2 ,购买一个必然是最优,如果这都不行那更大也不行 第二个询问也是同理 ,因此只需特判
CODE:
int main() { int T; ll a, b, c; scanf("%d", &T); while (T--) { ll ans1, ans2; scanf("%lld%lld%lld", &a, &b, &c); if (b != 1) { if (a < c) ans1 = 1; else ans1 = -1; } else { if (a < c) ans1 = 1; else ans1 = -1; } if (b * a <= c) ans2 = -1; else ans2 = b; printf("%lld %lld\n", ans1, ans2); } }
B:
给定一个01串,两人开始删串,每次可以删除“01” 或者“10” 最后不能删的人输。
显然,最终若全是1或者全是0或者空者输,因此可直接根据个数判断
CODE:
string s; int main() { int T; cin >> T; while (T--) { cin >> s; int l1, l2; l1 = l2 = 0; for (int i = 0; i < s.length(); i++) { if (s[i] == '1') l1++; else l2++; } if (min(l1, l2) & 1) puts("DA"); else puts("NET"); } return 0; }
C:
讲道理,此题不太懂在干什么,当时就照着这段代码模拟整合了一下,用到了前缀和 。 注意开longlong!!!
CODE;
string s; ll v[maxn]; int main() { int T; cin >> T; while (T--) { memset(v,0,sizeof v); cin >> s; ll res = 0; int tag = 0; for (ll i = 0; i < s.length(); i++) { if (s[i] == '+') v[i]++; else v[i]--; if (i) v[i] += v[i - 1]; if (v[i] < 0 && v[i] == tag -1) { tag--; res += i + 1; } } res+=(ll)s.length(); cout << res << endl; } }
D:
给定数组a, 你可以进行一次操作来翻转区间,问最终所有偶数位的最大和 。 下标从0开始。
当时其实已经做出来了,但是没判断vector为空导致最后几分钟没AC,懊悔不已。
考虑到有效的翻转其实就是选定一个端点为偶一个为奇数。 这样做的效果其实就是把这段区间的偶数位全部换成奇数位。
因此只要求出整段的最大差(利用差分),再加上原来的偶数位的和即可。 最大差只需跑一遍最大子段和。 注意从左往右和从右往左都跑一遍。开longlong
CODE:
ll a[maxn]; vector<ll> v1; vector<ll> v2; ll solve1() { if(v1.empty()) return 0; ll tmp = 0; ll now = v1[0]; ll ans = now; if (now > 0) tmp = now; for (int i = 1; i < v1.size(); i++) { tmp += v1[i]; if (tmp > ans) ans = tmp; if (tmp < 0) tmp = 0; } return max(0ll, ans); } ll solve2() { if(v2.empty()) return 0; ll tmp = 0; ll now = v2[0]; ll ans = now; if (now > 0) tmp = now; for (int i = 1; i < v2.size(); i++) { tmp += v2[i]; if (tmp > ans) ans = tmp; if (tmp < 0) tmp = 0; } return max(0ll, ans); } int main() { int T; int n; scanf("%d", &T); while (T--) { v1.clear(); v2.clear(); ll res = 0; scanf("%d", &n); if(n==1){ int tmp; scanf("%d",&tmp); printf("%d\n",tmp); continue; } ll res1, res2; res1 = res2 = 0; //int Max = 0; for (int i = 0; i < n; i++) { scanf("%lld", &a[i]); if (i & 1) res2 += a[i]; else res1 += a[i]; if (i%2) v1.push_back(a[i]-a[i-1]); } for (int i = 0; i < n; i++) { if (i%2 && i < n-1) v2.push_back(a[i]-a[i+1]); } res = max(solve1(),solve2()); printf("%lld\n", res1 + res); } }
E:
令f(X) 为X的各个位数之和。给定n,k 求出最小的X使得 ( sigma(f(x+i)) i=0~k ) = n 。
此题比较综合,思路和实现其实都不好想。
思路:最后变动的位数其实只有最后一位。所有其实可以考虑枚举最后一位。 由于希望X尽量小,我们自然希望中间用9填充,故可枚举中间9的个数,前面的数越小越好。
细节:考虑进位带来的影响。
CODE:
int get_sum(int s, int cnt) { int res = 0; for (int i = 0; i < cnt; i++) res += (s + i) % 10; return res; } inline void upd(string& have, const string& s) { if (have == "-1") have = s; else if (have.size() > s.size()) have = s; else if (have.size() == s.size() && have > s) have = s; } string get(int need) { string res = ""; if (need >= 9) res.push_back('8'), need -= 8; while (need >= 10) res.push_back('9'), need -= 9; if (need > 0) res.push_back('0' + need); reverse(res.begin(), res.end()); return res; } string solve(int n, int k) { k++; string best = "-1"; for (int s = 0; s <= 9; s++) { int need = n - get_sum(s, k); if (need < 0) continue; int l = min(k, 10 - s); int r = k - l; for (int c = 0; c < 20; c++) { int t = 9 * c; int tmp = need - l * t - r; if (tmp >= 0 && tmp % k == 0) { string cur = get(tmp / k); upd(best, cur + string(c, '9') + string(1, '0' + s)); } } } return best; } int main() { int T; scanf("%d", &T); while (T--) { int n, k; scanf("%d%d", &n, &k); cout << solve(n, k) << endl; } }
F:
n个家庭成一个环 给定数组a,b 对于每个i,可以分bi给第i个家庭或第 i+1个家庭 问能否使得每个家庭最终大于等于ai
首先这个问题是环,考虑先退化成链来考虑,问题就简化许多。 只需二分第一个家庭失去的b的大小,结果就呈现出单调性。只有此时得到的最小解就有可能是答案。因此只需最后再judge一遍即可。
CODE:
int a[maxn], b[maxn]; int r[maxn]; int n; bool check(int x) { r[0] = b[0] - x; for (int i = 1; i < n; i++) { r[i] = b[i] - max(0, a[i] - r[i-1]); if (r[i] < 0) return false; } return true; } bool Check(int x) { r[0] = b[0] - x; for (int i = 1; i < n; i++) { r[i] = b[i] - max(0, a[i] - r[i - 1]); if (r[i] < 0) return false; } return (r[n - 1] + x >= a[0]); } bool solve() { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", a + i); for (int i = 0; i < n; i++) scanf("%d", b + i); int l = 0, r = b[0]; while (l < r) { int mid = l + r + 1 >> 1; if (check(mid)) l = mid; else r = mid - 1; } if (Check(l)) return true; else return false; } int main() { int T; scanf("%d", &T); while (T--) { if (solve()) puts("YES"); else puts("NO"); } }