水题
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 5 int main() { 6 LL n, m, a, b; 7 cin >> n >> m >> a >> b; 8 n %= m; 9 LL ans = min(b * n, (m - n) * a); 10 cout << ans << endl; 11 return 0; 12 }
双指针
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 2e5 + 10; 4 int a[maxn]; 5 6 int main() { 7 int n, k, ans = 0; 8 scanf("%d %d", &n, &k); 9 for(int i = 1; i <= n; ++i) scanf("%d", a + i); 10 sort(a + 1, a + 1 + n); 11 int p = 1; 12 for(int i = 1; i <= n; i++) { 13 while(p < i && a[p] < a[i] - k) p++; 14 while(p < i && a[p] < a[i]) p++, ans++; 15 } 16 printf("%d\n", n - ans); 17 return 0; 18 }
C.Bracket Sequences Concatenation Problem
判下前后缀合法性
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 3e5 + 10; 4 typedef long long LL; 5 string str[maxn]; 6 char s[maxn]; 7 8 map<int, int> M; 9 10 int main() { 11 int n; 12 scanf("%d", &n); 13 for (int i = 1; i <= n; ++i) { 14 scanf("%s", s + 1); 15 str[i] = string(s + 1); 16 int l = strlen(s + 1), sum = 0, ok = 1; 17 for (int j = l; j >= 1; --j) { 18 if (s[j] == ')') sum++; 19 else sum--; 20 if(sum < 0) ok = 0; 21 } 22 if(ok) M[sum]++; 23 } 24 LL ans = 0; 25 for (int i = 1; i <= n; ++i) { 26 int l = str[i].length(), sum = 0, ok = 1; 27 for (int j = 0; j < l; ++j) { 28 if (str[i][j] == '(') sum++; 29 else sum--; 30 if(sum < 0) ok = 0; 31 } 32 if(ok && M.find(sum) != M.end()) ans += M[sum]; 33 } 34 cout << ans << endl; 35 return 0; 36 }
如果一个图有多个连通块,记一个连通块中的顶点集S1,S2=V-S1
补图中S1中所有点与S2中所有点都互相连接,故补图只有一个连通块
一个连通块可以连一条链构造 多个连通块可以用孤立点和菊花图 再特判几个点
1 #include <bits/stdc++.h> 2 using namespace std; 3 int G[1111][1111]; 4 5 int main() { 6 int n, a, b; 7 scanf("%d %d %d", &n, &a, &b); 8 if(a > 1 && b > 1 || n == 2 && a == 1 && b == 1 || n == 3 && a == 1 && b == 1) { 9 puts("NO"); 10 return 0; 11 } 12 puts("YES"); 13 if(a == 1 && b == 1) { 14 for(int i = 1; i <= n; ++i){ 15 for(int j = 1; j <= n; ++j) { 16 if(j == i + 1 || j == i - 1) putchar('1'); 17 else putchar('0'); 18 } 19 puts(""); 20 } 21 return 0; 22 } 23 int one = 1, zero = 0; 24 if(b > 1) swap(a, b), swap(one, zero); 25 for(int i = a + 1; i <= n; ++i) { 26 G[1][i] = G[i][1] = 1; 27 } 28 for(int i = 1; i <= n; ++i){ 29 for(int j = 1; j <= n; ++j) { 30 if(i == j) putchar('0'); 31 else if(G[i][j]) printf("%d", one); 32 else printf("%d", zero); 33 } 34 puts(""); 35 } 36 return 0; 37 }
暴力枚举倍数感觉是nlogn的
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const LL INF = 1e18; 5 const int maxn = 1e6 + 10; 6 int ban[maxn], L[maxn], a[maxn]; 7 8 int main() { 9 int n, m, k, s; 10 scanf("%d %d %d", &n, &m, &k); 11 for(int i = 1; i <= m; ++i) { 12 scanf("%d", &s); 13 ban[s] = 1; 14 } 15 for(int i = 1; i <= k; ++i) scanf("%d", a + i); 16 L[0] = ban[0] ? -1 : 0; 17 for(int i = 1; i < n; ++i) { 18 if(!ban[i]) L[i] = i; 19 else L[i] = L[i-1]; 20 } 21 LL ans = INF; 22 for(int i = 1; i <= k; ++i) { 23 int ok = 1, num = 0; 24 for(int j = 0; j < n; ) { 25 if(!ban[j]) num++, j += i; 26 else { 27 if(L[j] == -1 || j - L[j] >= i) {ok = 0; break;} 28 else num++, j += i - (j - L[j]); 29 } 30 } 31 if(ok) ans = min(ans, (LL) num * a[i]); 32 } 33 printf("%I64d\n", ans == INF ? -1 : ans); 34 return 0; 35 }
显然只用树边就可以构造了
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 2e5 + 10; 4 int a[maxn], u[maxn], v[maxn]; 5 int vis[maxn], ans[maxn]; 6 vector<int> G[maxn]; 7 8 int dfs(int x) { 9 vis[x] = 1; 10 int ret = a[x]; 11 for(int i = 0; i < G[x].size(); ++i) { 12 int to, d; 13 if(u[G[x][i]] == x) to = v[G[x][i]], d = 1; 14 else to = u[G[x][i]], d = -1; 15 if(vis[to]) continue; 16 int flow = dfs(to); 17 ans[G[x][i]] = d * flow; 18 ret += flow; 19 } 20 return ret; 21 } 22 23 int main() { 24 int n, m; 25 scanf("%d", &n); 26 for(int i = 1; i <= n; ++i) scanf("%d", a + i); 27 scanf("%d", &m); 28 for(int i = 1; i <= m; ++i) { 29 scanf("%d %d", u + i, v + i); 30 G[u[i]].push_back(i); 31 G[v[i]].push_back(i); 32 } 33 int ok = 1; 34 for(int i = 1; i <= n; ++i) { 35 if(vis[i]) continue; 36 if(dfs(i)) ok = 0; 37 } 38 if(!ok) puts("Impossible"); 39 else { 40 puts("Possible"); 41 for(int i = 1; i <= m; ++i) printf("%d\n", ans[i]); 42 } 43 return 0; 44 }
考虑求能被每个因子i整除的路径数再容斥出原问题的答案
枚举每个因子i,只连接两端都能被i整除的边,并用并查集维护连通块大小,可以计算一个块内路径为$\frac{(sz - 1) \times sz }{ 2}+ sz$
因为每个数只有根号个因子,所以这样是1.5次的
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 2e5 + 10; 4 typedef long long LL; 5 int a[maxn], cnt[maxn]; 6 LL ans[maxn]; 7 8 typedef pair<int, int> pii; 9 vector<pii> G[maxn]; 10 11 int fa[maxn], r[maxn]; 12 int Find(int x) { 13 return fa[x] == x ? x : fa[x] = Find(fa[x]); 14 } 15 vector<int> v; 16 void Union(int x, int y) { 17 x = Find(x), y = Find(y); 18 if(x == y) return; 19 fa[x] = y, r[y] += r[x]; 20 v.push_back(x); 21 v.push_back(y); 22 } 23 void cln() { 24 for(int i = 0; i < v.size(); ++i) fa[v[i]] = v[i], r[v[i]] = 1; 25 v.clear(); 26 } 27 28 int main() { 29 int n; 30 scanf("%d", &n); 31 for(int i = 1; i <= n; ++i) scanf("%d", a + i), cnt[a[i]]++, fa[i] = i, r[i] = 1; 32 for(int i = 1; i < n; ++i) { 33 int u, v; 34 scanf("%d %d", &u, &v); 35 G[__gcd(a[u], a[v])].push_back(pii(u, v)); 36 } 37 for(int i = 1; i < maxn; ++i) { 38 LL tmp = 0; 39 for(int j = i; j < maxn; j += i) { 40 tmp += cnt[j]; 41 for(int k = 0; k < G[j].size(); ++k) { 42 int u = Find(G[j][k].first), v = Find(G[j][k].second); 43 if(u == v) continue; 44 tmp -= (LL) r[u] * (r[u] - 1) / 2 + r[u]; 45 tmp -= (LL) r[v] * (r[v] - 1) / 2 + r[v]; 46 Union(u, v), u = Find(u); 47 tmp += (LL) r[u] * (r[u] - 1) / 2 + r[u]; 48 } 49 } 50 ans[i] = tmp, cln(); 51 } 52 for(int i = maxn - 1; i >= 1; --i) 53 for(int j = i + i; j < maxn; j += i) 54 ans[i] -= ans[j]; 55 for(int i = 1; i < maxn; ++i) if(ans[i]) printf("%d %I64d\n", i, ans[i]); 56 return 0; 57 }
来源:https://www.cnblogs.com/Aguin/p/9173992.html