#include<bits/stdc++.h> #define mem(arry, in) memset(arry, in, sizeof(arry)) using namespace std; typedef long long ll; typedef pair<int, int> P; int main() { ll n, m, a, b; cin >> n >> m >> a >> b; n = n % m; ll res1 = (m - n) * a; ll res2 = n * b; cout << min(res1, res2) << endl; }
题解:从小到大枚举,观察是否能被前一个( i + 1 )数消掉。注意相同的数。
#include<bits/stdc++.h> #define mem(arry, in) memset(arry, in, sizeof(arry)) using namespace std; typedef long long ll; typedef pair<int, int> P; const int maxn = 200005; int n, K; int a[maxn], use[maxn * 10];
int main() { cin >> n >> K; for(int i = 1; i <= n; i++){ int tp; cin >> tp; use[tp]++; } int m = 0; for(int i = 1; i <= 1000000; i++) if(use[i]) a[++m] = i; //for(int i = 1; i <= m; i++) cout << a[i] << " "; //cout << endl; int tp = a[1]; int cnt = 0; for(int i = 2; i <= m; i++){ if(a[i] <= tp + K) cnt += use[tp]; tp = a[i]; } cout << n - cnt << endl; return 0; }
C. Bracket Sequences Concatenation Problem
题解:能匹配的情况分别统计一下,比如"(" 和 ")","((" 和 "))",、、、、
#include<bits/stdc++.h> #define mem(arry, in) memset(arry, in, sizeof(arry)) using namespace std; typedef long long ll; typedef pair<int, int> P; const int maxn = 300005; int n, cnt, m; int a[maxn], b[maxn]; stack<char> q; int main() { while(!q.empty()) q.pop(); cin >> n; cnt = 0; for(int i = 0; i < n; i++){ char s[maxn]; scanf("%s", s); m = strlen(s); q.push(s[0]); for(int j = 1; j < m; j++){ if(q.empty()) q.push(s[j]); else{ if(s[j] == ')'){ if(q.top() == '(') q.pop(); else q.push(s[j]); } else q.push(s[j]); } } if(q.empty()) cnt++; else{ int g = 0, t = 0; while(!q.empty()){ if(q.top() == '(') g++; else t++; q.pop(); } if(g && !t) a[g]++; if(!g && t) b[t]++; } } ll res = (ll)cnt * (ll)cnt; for(int i = 0; i <= maxn; i++) if(a[i] && b[i]) res += (ll)a[i] * (ll)b[i]; cout << res << endl; return 0; }
没理解到题意,看代码貌似灯的照亮范围只能选1~k中的一种,所以可以直接暴力求解。n(1 + 1/2 + 1/3 + 1/4 + 1/5 + ·····+ 1/n) = nlog(n)
如果灯的亮度可以在1~k中任意选,感觉会是个背包或者区间DP
#include<bits/stdc++.h> #define ll long long #define P pair<int,int> #define maxn (int)1e6 + 7 #define INF (unsigned long long int)1e18 #define mem(arry, in) memset(arry, in, sizeof(arry)) using namespace std; int n, m, k; int use[maxn], a[maxn], s[maxn]; int main() { int tp, l = 0; cin >> n >> m >> k; for(int i = 1; i <= m; i++) scanf("%d", &tp), use[tp] = 1; for(int i = 1; i <= k; i++) scanf("%d", &a[i]); if(use[0]) { cout << -1 << endl; return 0; } for(int i = 1; i < n; i++){ if(use[i]) s[i] = s[i - 1] + 1; else s[i] = 0; l = max(l, s[i]); } ll res = INF; for(int i = l + 1; i <= k; i++){ int cnt = 0; for(int j = 0; j < n; j += i){ if(use[j]) j -= s[j]; cnt++; } res = min(res, (ll)cnt * (ll)a[i]); } cout << (res == INF ? -1 : res) << endl; return 0; }
题解:如果sigma(a[i])!=0,那么一定不能构造出来。一条边的端点假设是 u, v,对u来说是进流(出流)的边,对v来说必定是出流(进流)的边,所以在 a1 + a2 + a3 + ······ + am 这个式子中,这条边必定出现两次,且互为相反数,故sigma(a[i])=0。对一个点来说只考虑进流和出流的情况,所以构造一颗生成树,树的叶子要么是进流,要么是出流,自底向上计算。
实现的话DFS,不一定用并查集。记录方向也是小技巧。
#pragma warning(disable:4996) #include<map> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define P pair<int,int> #define maxn (int)2e5 + 7 #define INF (unsigned long long int)1e18 #define mem(arry, in) memset(arry, in, sizeof(arry)) using namespace std; int n, m; int a[maxn], use[maxn], ans[maxn]; vector<P> g[maxn]; void DFS(int u) { use[u] = 1; for (auto x : g[u]) { int v = x.first; if (use[v]) continue; DFS(v); ans[abs(x.second)] = (x.second > 0 ? a[v] : -a[v]); a[u] += a[v]; } } int main() { int res = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]), res += a[i]; scanf("%d", &m); for (int i = 1; i <= m; i++) { int u, v; scanf("%d %d", &u, &v); g[u].push_back(P(v, i)); g[v].push_back(P(u, -i)); } if (res) { puts("Impossible"); } else { puts("Possible"); DFS(1); for (int i = 1; i <= m; i++) printf("%d ", ans[i]); } return 0; }
注意单独的一个点也可以称为一条路径。
超级暴力的做法,以1为根的树,暴力的从叶子向根记录所有路径的gcd值。有小于1s的做法,得去学习一下
vector<int> e[maxn]; map<int, ll> mp[maxn]; int n, a[maxn]; ll cnt[maxn]; int gcd(int a,int b) { return !b ? a : gcd(b, a % b); } void DFS(int u, int p){ mp[u][a[u]]++; for(int v : e[u]){ if(v == p) continue; DFS(v, u); map<int, ll> :: iterator itu, itv; for(itu = mp[u].begin(); itu != mp[u].end(); itu++){ for(itv = mp[v].begin(); itv != mp[v].end(); itv++){ cnt[gcd(itu->first, itv->first)] += (itu->second * itv->second); } }
//存子树的gcd值!!!! for(itv = mp[v].begin(); itv != mp[v].end(); itv++){ mp[u][gcd(a[u], itv->first)] += itv->second; } mp[v].clear(); } }