[HG]奋斗赛G
T1
题目描述
安娜斯塔西娅喜欢去乌日扬迪安中央公园散步。 但她对简单的散步不感兴趣,于是她开始收集公园里的鹅卵石。 一开始,她决定收集所有她能在公园里找到的鹅卵石。
她只有两个口袋。 她能在每个口袋里同时放最多k个鹅卵石。第i种鹅卵石有w[i]个。 安娜斯塔西娅很有责任感,所以她从不把不同类型的鹅卵石混在一个口袋里。 然而,她可以把不同种类的鹅卵石放在不同的口袋。 不幸的是,她不能把所有的时间都花在收集鹅卵石上,所以她每天只能从公园里收集一次鹅卵石。
考虑到安娜斯塔西娅不能把不同类型的鹅卵石放在同一个口袋里,请帮助她找到收集乌日扬甸中央公园所有鹅卵石所需的最短天数。
解法:直接模拟
#include <cstdio> #define ll long long inline ll read(){ ll x = 0; int zf = 1; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf; } int main(){ int n = read(), k = read(), a; ll tot = 0; for (int i = 0; i < n; ++i) a = read(), tot += (a % k) ? (a / k + 1) : (a / k); tot = (tot & 1) ? ((tot >> 1) + 1) : (tot >> 1); printf("%lld", tot); return 0; }
T2
题意:给你一个等比数列,首项为b1,公比为q,现在Masha在黑板上从首项开始书写这个等比数列,直到数列某项的绝对值大于l,给定m个整数,若该等比数列中的某项等同于这m个整数,则不会被写出。
问Masha会写出多少个数字?如果她会写出无穷多个数字,输出inf
注意: b1,q可能为0
解法:
特判q为0,1,-1;b1为0的情况
然后其他情况直接用set暴力模拟即可
有一个坑点:
----如果abs(b) > l即使q=0,0没有限制也要输出0,蒟蒻不知道为什么
#include <cstdio> #include <cmath> #include <set> #define ll long long using namespace std; inline ll read(){ ll x = 0; int zf = 1; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf; } set<ll> st; int main(){ ll b = read(), q = read(), l = read(), m = read(); for (int i = 1; i <= m; ++i) st.insert(read()); if (q == 0){ if (st.find(0) != st.end() || (l < 0)){ if (st.find(b) != st.end() || (abs(b) > l)) printf("0"); else printf("1"); } else if (abs(b) > l) printf("0"); else printf("inf"); return 0; } else if (q == 1){ if ((abs(b) > l) || st.find(b) != st.end()) printf("0"); else printf("inf"); return 0; } else if (q == -1){ if (abs(b) > l){ printf("0"); return 0; } if (st.find(b) == st.end()){ printf("inf"); return 0; } if (st.find(-b) == st.end()){ printf("inf"); return 0; } printf("0"); return 0; } else if (b == 0){ if (st.find(0) != st.end() || (l < 0)) printf("0"); else printf("inf"); return 0; } else{ int cnt = 0; for (ll i = b; abs(i) <= l; i *= q){ if (st.find(i) == st.end()) ++cnt; } printf("%d", cnt); } return 0; }
T3
题意:
定义一个函数,函数如下(请找个markdown编辑器贴一下):
$f[l,r]=\sum_{i=l}^{r-1}|a_i-a_{i-1}|\times(-1)^{i-l}$
|x|表示x的绝对值。
现在给你一个函数,请取恰当的l,r使f值最大,请输出最大的f值
解法:不说了直接DP
#include <cstdio> #include <cmath> #include <algorithm> #define max(a,b) ((a>b)?a:b) #define ll long long using namespace std; inline ll read(){ ll x = 0; int zf = 1; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf; } int a[100005]; ll f[100005][2]; int main(){ int n = read(); for (int i = 1; i <= n; ++i) a[i] = read(); for (int i = 1; i < n; ++i) a[i] = abs(a[i] - a[i + 1]); ll ans = a[1]; f[1][1] = a[1], f[1][0] = 0; for (int i = 2; i < n; ++i){ if (i & 1){ f[i][1] = max(f[i - 1][1] + a[i], a[i]); f[i][0] = f[i - 1][0] - a[i]; } else{ f[i][0] = max(f[i - 1][0] + a[i], a[i]); f[i][1] = f[i - 1][1] - a[i]; } ans = max(max(f[i][0], f[i][1]), ans); } printf("%lld", ans); return 0; }
T4
题意:总共有n个节点,m条路径,要求其中m-2条路径走两遍,剩下2条路径仅走一遍,问不同的路径总数有多少,如果仅走一遍的两条边不同则将这两条路径视为不同。
解法:DFS判图的联通性+数学
#include <cstdio> #define ll long long struct Edge{ int to, next; } edges[2000005]; int head[1000005], edge_num = 0; int cnt[1000005]; inline ll read(){ ll x = 0; int zf = 1; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf; } inline void addEdge(int from, int to){ ++cnt[from]; edges[++edge_num] = (Edge){to, head[from]}; head[from] = edge_num; } bool vis[1000005]; int rd[1000005]; void DFS(int u){ for(int c_e = head[u]; c_e; c_e = edges[c_e].next){ int v = edges[c_e].to; if(!vis[v]){ vis[v] = 1; DFS(v); } } } inline ll cac(ll num){ return (((num - 1) * num) >> 1); } int main(){ int n = read(), m = read(); ll zh = 0; for(int i = 1; i <= m; i++){ int u = read(), v = read(); ++rd[u], ++rd[v]; if(u != v) addEdge(u, v), addEdge(v, u); else ++zh; } for(int i = 1; i <= n; ++i) if(head[i] != 0){ vis[i] = 1, DFS(i); break; } ll ans = 0; for(int i = 1; i <= n; ++i) if(!vis[i] && rd[i]){ printf("0"); return 0; } for(int i = 1; i <= n; ++i) ans += 1ll * cac(cnt[i]); ans += zh * (m - 1) - cac(zh); printf("%lld", ans); return 0; }
T5
题意:有k种可乐,第i瓶可乐的CO2浓度是ai/1000,问要配置出浓度n/1000的可乐,最少需要几瓶可乐。
解法:题目very interestring但其实就是个广搜
#include <cstdio> #include <algorithm> #include <queue> #define ll long long using namespace std; int a[1000010]; int ans[2005]; bool vis[2005]; inline ll read(){ ll x = 0; int zf = 1; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf; } queue<int> que; int main(){ int n = read(), k = read(); for(int i = 0; i < k; ++i) a[i] = read() - n; sort(a, a + k); k = unique(a, a + k) - a; if(a[0] * a[k - 1] > 0){ printf("-1\n"); return 0; } for(int i = 0; i < k; ++i){ que.push(a[i]); ans[a[i] + 1000] = 1, vis[a[i] + 1000] = 1; } int u; while(!que.empty() && !vis[1000]){ u = que.front(), que.pop(); for(int i = 0; i < k; ++i){ if((u + a[i]) <= 1000 && (u + a[i]) >= -1000 && !vis[u + a[i] + 1000]){ que.push(u + a[i]); vis[u + a[i] + 1000] = 1; ans[u + a[i] + 1000] = ans[u + 1000] + 1; } } } printf("%d", ans[1000]); return 0; }