水题

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
