20161026测试总结

感谢出题人送我的生日礼物,人生第一次AK,23333…

T1

一维水dp,为什么某些人要作死写二维
f[0] 表示1的长度,f[1]表示符合题意的18的最大长度,f[2]表示符合题意的190最大长度,f[3]表示符合题意的1807最大长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <bits/stdc++.h>
using namespace std;
char str[1000005];
int f[5];
inline void solve(const char *str) {
while (*str) {
switch (*str) {
case '1':
f[0]++;
break;
case '8':
if (f[0])
f[1] = max(f[1], f[0]) + 1;
break;
case '0':
if (f[1])
f[2] = max(f[1], f[2]) + 1;
break;
case '7':
if (f[2])
f[3] = max(f[2], f[3]) + 1;
break;
}
str++;
}
cout << f[3];
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> str;
solve(str);
return 0;
}

T2

100分乱搞

此题一看就应该先建一个超级点S,然后跑一遍dijkstra或SPFA,然后我们就可以的到一个最短路径图,接着就乱搞了233,像20161025测试T3一样,交换建图,然后按w排序,贪心,用并查集判断一下就好了…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <bits/stdc++.h>
using namespace std;
const int iol = 1024 * 1024;
char buf[iol], *ioh, *iot, ioc;
bool iosig;
inline char read() {
if (ioh == iot) {
iot = (ioh = buf) + fread(buf, 1, iol, stdin);
if (ioh == iot) return -1;
}
return *ioh++;
}
template<class T>
inline bool read(T &x) {
iosig = false;
for (ioc = read(); !isdigit(ioc); ioc = read()) {
if (ioc == -1) return false;
if (ioc == '-') iosig = true;
}
x = 0;
while (ioc == '0') ioc = read();
for (; isdigit(ioc); ioc = read())
x = (x << 1) + (x << 3) + (ioc ^ '0');
ioh--;
if (iosig) x = -x;
return true;
}
struct DisjointSet {
int *rank, *father, size;
inline int get(int x) {
register int p = x, i;
while (p != father[p]) p = father[p];
while (x != p) i = father[x], father[x] = p, x = i;
return p;
}
inline void put(int x, int y) {
x = get(x), y = get(y);
if (rank[x] > rank[y]) father[y] = x;
else {
father[x] = y;
if (rank[x] == rank[y]) rank[y]++;
}
}
inline void init(int x) {
rank[x] = 0, father[x] = x;
}
DisjointSet(int n) : rank(new int[n + 1]), father(new int[n + 1]), size(n + 1) {
for (register int i = 1; i <= n; i++)
father[i] = i;
}
} *s;
int n, m;
#define INF 0x3fffffff
const int MAX = 100000 + 50;
struct Node {
int v;
long long w;
Node() {}
Node(int v0, long long w0) : v(v0), w(w0) {}
inline bool operator < (const Node &b) const {
return w < b.w;
}
};
bool vis[MAX], toPush[MAX];
vector<Node> edge[MAX];

long long dis[MAX];
/*inline bool spfa() {
deque<int> dq;
register int now, to;
fill(dis + 1, dis + n + 1, INF), fill(vis + 1, vis + n + 1, false), fill(inQueSum + 1, inQueSum + n + 1, 0);
for (register int i = 1; i <= n; i++)
if(toPush[i])
dq.push_back(i), vis[i] = true, dis[i] = 0, inQueSum[i]++;
while (!dq.empty()) {
now = dq.front(), dq.pop_front(), vis[now] = false;
for (register int i = 0; i < edge[now].size(); i++) {
to = edge[now][i].v;
if ((dis[now] < INF) && (dis[to] > dis[now] + edge[now][i].w)) {
dis[to] = dis[now] + edge[now][i].w;
if (!vis[to]) {
vis[to] = true, inQueSum[to]++;
if (inQueSum[to] == n) return false;
if ((!dq.empty()) && (dis[to] <= dis[dq.front()]))
dq.push_front(to);
else
dq.push_back(to);
}
}
}
}
return true;
}*/
inline void spfa() {
queue<int> q;
memset(dis, 127, sizeof(dis));
memset(vis, false, sizeof(vis));
for (register int i = 1; i <= n; i++)
if (toPush[i])
q.push(i), vis[i] = true, dis[i] = 0;
while (!q.empty()) {
int now = q.front();
q.pop();
vis[now] = false;
for (int i = 0; i < edge[now].size(); ++i) {
Node *x = &edge[now][i];
if (dis[x->v] > dis[now] + x->w) {
dis[x->v] = dis[now] + x->w;
if (!vis[x->v]) vis[x->v] = true, q.push(x->v);
}
}
}
}
inline void addEdge(int u, int v, int w) {
edge[u].push_back(Node(v, w));
edge[v].push_back(Node(u, w));
}
inline void init() {
read(n), read(m);
for (register int i = 1; i <= n; i++)
read(toPush[i]);
for (register int i = 1, u, v, w; i <= m; i++)
read(u), read(v), read(w), addEdge(u, v, w);
spfa();
}
struct data {
int u, v;
long long w;
inline bool operator < (const data &b) const {
return w < b.w;
}
} d[400000 + 20];
int cnt;
long long ans;
inline void solve() {
for (register int i = 1; i <= n; i++) {
if (!toPush[i]) {
for (register int j = 0; j < edge[i].size(); j++) {
Node *e = &edge[i][j];
if (dis[e->v] + e->w == dis[i])
d[++cnt].u = e->v, d[cnt].v = i, d[cnt].w = e->w;
}
}
}
s = new DisjointSet(n + 1);
register int k = 0;
for (register int i = 1; i <= n; i++)
if (toPush[i])
s->put(i, n + 1), k++;
sort(d + 1, d + 1 + cnt);
for (register int i = 1; i <= cnt; i++) {
if (s->get(d[i].u) != s->get(d[i].v)) {
s->put(d[i].u, d[i].v);
k++, ans += d[i].w;
if (k == n) break;
}
}
if (k != n) cout << "impossible";
else cout << ans;
}
int main() {
init();
solve();
return 0;
}

正解

还是先建图跑SPFA,这是我们得到了一个最短路径图,此时这个问题就变为取权值最小的边的集合,使得这幅图连接,于是我们求一个最小生成树就行了…
std太丑,这里就不贴了…

T3

100分容斥+莫比乌斯+乱搞

一看此题题目gcd,就是和数论有关的东西(gcd显然不能搞),自然而然联想到莫比乌斯函数,注意到方案数是肯定得容斥的,我们先令h[x]为数x的出现次数,令sum[i]为 $\sum_{j = i}^{MAXN}h[j] $ ,此时我们就可以枚举1~MAXN,如果sum[i]并且mu[i]不为0,我们可以分一下两种情况,得到全集,然后容斥就行了。
垃圾windows评测机,只能开鬼畜优化了2333…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <bits/stdc++.h>
using namespace std;
const int iol = 1024 * 1024;
char buf[iol], *ioh, *iot, ioc;
inline __attribute__((optimize("Ofast"))) __attribute__((always_inline)) char read() {
if (ioh == iot) {
iot = (ioh = buf) + fread(buf, 1, iol, stdin);
if (ioh == iot) return -1;
}
return *ioh++;
}
template<class T>
inline __attribute__((optimize("Ofast"))) __attribute__((always_inline)) void read(T &x) {
for (ioc = read(); !isdigit(ioc); ioc = read());
x = 0;
for (; isdigit(ioc); ioc = read())
x = x * 10 + (ioc ^ '0');
}
const int MAXN = 10000005;
#define mod 1000000007

bool vis[MAXN];
int mu[MAXN], prime[MAXN], tot;
__attribute__((optimize("Ofast"))) inline void getMu() {
mu[1] = 1;
for (register int i = 2; i < MAXN; i++) {
if (!vis[i]) {
prime[tot++] = i;
mu[i] = -1;
}
for (register int j = 0; j < tot && i * prime[j] < MAXN; j++) {
vis[i * prime[j]] = true;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
}
else mu[i * prime[j]] = -mu[i];
}
}
}
long long h[MAXN], sum[MAXN];
int n;
__attribute__((optimize("Ofast"))) int main() {
read(n);
int max = 0;
for (register int i = 0, x; i < n; i++)
read(x), h[x]++;
for (register int i = 1; i < MAXN; i++)
for (register int j = i; j < MAXN; j += i)
sum[i] += h[j];
getMu();
long long a = 0, b = 0;
h[0] = 1;
for (register int i = 1; i < MAXN; i++)
h[i] = (h[i - 1] << 1) % mod;
for (register int i = 1; i < MAXN; i++) {
if (sum[i] && mu[i]) {
if (mu[i] == 1)
a = (a + h[sum[i]] - 1) % mod, b = (b + h[sum[i] - 1] * sum[i]) % mod;
else
a = ((a - h[sum[i]] + 1) % mod + mod) % mod, b = ((b - h[sum[i] - 1] * sum[i]) % mod + mod) % mod;
}
}
cout << (((b << 1) - a * n) % mod + mod) % mod;
return 0;
}

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×