SGU150-159 Solution更好的阅读体验戳此进入题面链接150. Mr. Beetle II题面输入格式ExamplesSolutionCode151. Construct a triangle题面ExamplesSolutionCode152. Making round题面ExamplesSolutionCode153. Playing with matches题面ExamplesSolutionCode154. Factorial题面ExamplesSolutionCode155. Cartesian Tree题面ExamplesSolutionCode156. Strange Graph题面ExamplesSolutionCode157. Patience题面ExamplesSolutionCode题面SolutionCode题面SolutionCode题面SolutionCode题面SolutionCode题面SolutionCode题面SolutionCodeUPD
给定平面直角坐标系中的起点坐标 no solution
。
Input_1
12 3 4 -1 3
Output_1
xxxxxxxxxx
113 0
难度不高,但细节颇多。
不难想到数据范围较小,可以枚举区间内的所有横坐标,然后通过斜率和分类讨论计算横坐标对应的纵坐标的数量和范围,找到对应的方格即可。同时不难想到若
x1
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22
23
24
25template < typename T = int >
26inline T read(void);
27
28struct Coord{int x, y;}S, T;
29int N;
30
31int main(){
32 S.x = read(), S.y = read(), T.x = read(), T.y = read(); N = read();
33 if(S.x == T.x || S.y == T.y)printf("no solution\n"), exit(0);
34 T.x -= S.x, T.y -= S.y;
35 // printf("T : %d, %d\n", T.x, T.y);
36 int cur(0);
37 for(int X = 0; X != T.x; X += NXTX){
38 ll Y1 = (ll)X * T.y / T.x + (T.y < 0 ? NXTY : 0);
39 ll Y2 = (ll)(X + NXTX) * T.y / T.x + (T.y < 0 ? ((ll)(X + NXTX) * T.y % T.x ? NXTY : 0) : ((ll)(X + NXTX) * T.y % T.x ? 0 : -NXTY));
40 // printf("%d -> %lld, %lld\n", X, Y1, Y2);
41 cur += abs(Y2 - Y1) + 1;
42 if(cur >= N)printf("%d %lld\n", S.x + X + (T.x < 0 ? -1 : 0), S.y + (Y2 - NXTY * (cur - N))), exit(0);
43 }printf("no solution\n"), exit(0);
44 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
45 return 0;
46}
47
48template < typename T >
49inline T read(void){
50 T ret(0);
51 int flag(1);
52 char c = getchar();
53 while(c != '-' && !isdigit(c))c = getchar();
54 if(c == '-')flag = -1, c = getchar();
55 while(isdigit(c)){
56 ret *= 10;
57 ret += int(c - '0');
58 c = getchar();
59 }
60 ret *= flag;
61 return ret;
62}
对于 Mission impossible
。
特别地,对于本题的数据,允许
Input_1
xxxxxxxxxx
115 5 3
Output_1
xxxxxxxxxx
310.00000 3.00000
2-4.00000 0.00000
34.00000 0.00000
首先不难想到该三角形可以任意平移,所以考虑固定点
不难发现方程非线性,可解,仅需额外判断是否有解即可。
仍需注意一个额外的细节,判断无解时需要和
xxxxxxxxxx
571
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22
23
24template < typename T = int >
25inline T read(void);
26
27ld c, b, m;
28
29int main(){
30 scanf("%Lf%Lf%Lf", &c, &b, &m);
31 ld y = (ld)(4 * m * m - b * b - c * c) / (ld)(2 * c);
32 ld x = (ld)b * b - y * y;
33 if(x < -EPS)printf("Mission impossible\n"), exit(0);
34 if(fabs(x) <= EPS)x = 0.0;
35 if(fabs(y) <= EPS)y = 0.0;
36 x = sqrt(x);
37 printf("0.00000 0.00000\n0.00000 %.5Lf\n", c);
38 printf("%.5Lf %.5Lf\n", x, y);
39 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
40 return 0;
41}
42
43template < typename T >
44inline T read(void){
45 T ret(0);
46 int flag(1);
47 char c = getchar();
48 while(c != '-' && !isdigit(c))c = getchar();
49 if(c == '-')flag = -1, c = getchar();
50 while(isdigit(c)){
51 ret *= 10;
52 ret += int(c - '0');
53 c = getchar();
54 }
55 ret *= flag;
56 return ret;
57}
给定序列 No solution
。
Input_1
xxxxxxxxxx
212
210 10
Output_1
xxxxxxxxxx
1150 50
钦定均为向下取整,令钦定后的和为
xxxxxxxxxx
581
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25int N;
26int a[11000];
27int sum(0);
28int tot(0);
29basic_string < int > rem;
30
31int main(){
32 N = read();
33 for(int i = 1; i <= N; ++i)sum += a[i] = read();
34 for(int i = 1; i <= N; ++i){
35 if(a[i] * 100 % sum)rem += i;
36 tot += a[i] = (a[i] * 100 / sum);
37 }if(100 - tot > (int)rem.size())printf("No solution\n"), exit(0);
38 for(int i = 1; i <= 100 - tot; ++i)a[rem.at(i - 1)]++;
39 for(int i = 1; i <= N; ++i)printf("%d%c", a[i], i == N ? '\n' : ' ');
40 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
41 return 0;
42}
43
44template < typename T >
45inline T read(void){
46 T ret(0);
47 int flag(1);
48 char c = getchar();
49 while(c != '-' && !isdigit(c))c = getchar();
50 if(c == '-')flag = -1, c = getchar();
51 while(isdigit(c)){
52 ret *= 10;
53 ret += int(c - '0');
54 c = getchar();
55 }
56 ret *= flag;
57 return ret;
58}
存在 FIRST PLAYER MUST WIN
,后手必胜输出 SECOND PLAYER MUST WIN
。存在
Input_1
xxxxxxxxxx
311
25 3
32 3 5
Output_1
xxxxxxxxxx
11SECOND PLAYER MUST WIN
一道挺好的博弈论的题。
对于这种类型题不难想到
转移显然,即考虑是否所有子状态均为必胜,是则此状态必输,反之必胜。
发现这个的复杂度是
xxxxxxxxxx
701
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25int N, M;
26int P[10];
27bitset < 1300 > SG;
28
29int main(){
30 int T = read();
31 while(T--){
32 SG.reset();
33 N = read(), M = read();
34 P[0] = 1;
35 for(int i = 1; i <= M; ++i)P[i] = read();
36 SG[0] = true;
37 for(int i = 1; i <= 1200; ++i)
38 for(int p = 0; p <= M; ++p)
39 if(i - P[p] >= 0)
40 SG[i] = SG[i] | (SG[i - P[p]] ^ 1);
41 int rlen(-1);
42 for(int len = 1; len <= 520; ++len){
43 bool flag(true);
44 for(int s = 0; s <= 1100 - len * 2 + 10; s += len)
45 for(int i = s; i <= s + len - 1; ++i)
46 if(SG[i] != SG[i + len]){flag = false; break;}
47 if(flag){rlen = len; break;}
48 }//printf("rlen = %d\n", rlen);
49 // for(int i = 0; i <= 20; ++i)printf("SG[%d] = %d\n", i, SG[i] ? 1 : 0);
50 printf("%s\n", SG[N % rlen] ? "FIRST PLAYER MUST WIN" : "SECOND PLAYER MUST WIN");
51 }
52 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
53 return 0;
54}
55
56template < typename T >
57inline T read(void){
58 T ret(0);
59 int flag(1);
60 char c = getchar();
61 while(c != '-' && !isdigit(c))c = getchar();
62 if(c == '-')flag = -1, c = getchar();
63 while(isdigit(c)){
64 ret *= 10;
65 ret += int(c - '0');
66 c = getchar();
67 }
68 ret *= flag;
69 return ret;
70}
给定 No solution
。
Input_1
xxxxxxxxxx
112
Output_1
xxxxxxxxxx
1110
简单数论,经典套路。
显然从式子里拆出来
显然
具体式子显然为:
注意:需要特判
xxxxxxxxxx
621
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25ll Q;
26ll ctot;
27
28ll Check(ll n){
29 ll cur(5), tot(0);
30 while(cur <= n)tot += n / cur, cur *= 5;
31 return tot;
32}
33
34int main(){
35 Q = read();
36 if(!Q)printf("1\n"), exit(0);
37 ll l = 0, r = (int)(5e8), ans(-1);
38 while(l <= r){
39 ll mid = (l + r) >> 1;
40 if(Check(mid) >= Q)ans = mid, r = mid - 1;
41 else l = mid + 1;
42 }if(!~ans || Check(ans) != Q)printf("No solution\n"), exit(0);
43 printf("%lld\n", ans);
44 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
45 return 0;
46}
47
48template < typename T >
49inline T read(void){
50 T ret(0);
51 int flag(1);
52 char c = getchar();
53 while(c != '-' && !isdigit(c))c = getchar();
54 if(c == '-')flag = -1, c = getchar();
55 while(isdigit(c)){
56 ret *= 10;
57 ret += int(c - '0');
58 c = getchar();
59 }
60 ret *= flag;
61 return ret;
62}
给定
Input_1
xxxxxxxxxx
817
25 4
32 2
43 9
50 5
61 3
76 6
84 11
Output_1
xxxxxxxxxx
81YES
22 3 6
30 5 1
41 0 7
55 0 0
62 4 0
71 0 0
83 0 0
笛卡尔树模板,处理好各种映射之间的关系即可。
xxxxxxxxxx
741
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25int N;
26struct Node{
27 int idx, k, v;
28 friend const bool operator < (const Node &a, const Node &b){
29 return a.k < b.k;
30 }
31}nod[51000];
32unordered_map < int, int > mp, idx;
33int lson[51000], rson[51000], fa[51000];
34stack < int > cur;
35
36int main(){
37 N = read();
38 for(int i = 1; i <= N; ++i){
39 int k = read(), v = read();
40 nod[i] = Node{i, k, v};
41 mp.insert({k, v});
42 idx.insert({k, i});
43 }sort(nod + 1, nod + N + 1);
44 for(int i = 1; i <= N; ++i){
45 while(!cur.empty() && mp[cur.top()] > nod[i].v)
46 lson[nod[i].idx] = idx[cur.top()], cur.pop();
47 if(!cur.empty())rson[idx[cur.top()]] = nod[i].idx;
48 cur.push(nod[i].k);
49 }for(int i = 1; i <= N; ++i)
50 fa[lson[i]] = i, fa[rson[i]] = i;
51 int cnt(0);
52 for(int i = 1; i <= N; ++i)if(!fa[i])++cnt;
53 if(cnt > 1)printf("NO\n"), exit(0);
54 printf("YES\n");
55 for(int i = 1; i <= N; ++i)printf("%d %d %d\n", fa[i], lson[i], rson[i]);
56 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
57 return 0;
58}
59
60template < typename T >
61inline T read(void){
62 T ret(0);
63 int flag(1);
64 char c = getchar();
65 while(c != '-' && !isdigit(c))c = getchar();
66 if(c == '-')flag = -1, c = getchar();
67 while(isdigit(c)){
68 ret *= 10;
69 ret += int(c - '0');
70 c = getchar();
71 }
72 ret *= flag;
73 return ret;
74}
给定
点
若点
若点
你需要判断该图是否存在哈密尔顿回路,若存在则输出任意一个,反之输出 -1
。
Input_1
xxxxxxxxxx
214 4
21 2 2 3 3 4 4 1
Output_1
xxxxxxxxxx
111 2 3 4
Input_2
xxxxxxxxxx
319 12
21 2 2 3 3 1 1 4 2 5 3 6
34 7 5 8 6 9 7 8 8 9 9 7
Output_2
xxxxxxxxxx
11-1
一道十分高妙的题,思路不难但是构造方案还是需要亿些细节的。
首先根据题意,若
如果按照一般的构造欧拉回路的思路,我们会发现将欧拉回路还原回哈密尔顿回路是复杂的,因为我们是需要考虑缩完的两个点之间的边在原图中是哪些点,似乎可以维护但极为复杂,细节过多,所以这里有一个特别高妙的做法。
可以参考代码中 SetAns
函数,如此实现是可以保证,对于缩点后的没有连向其它新图中的点的旧点,当遍历到其之后就不会接着遍历,然后直接记录,反之则会继续找到新的点。可以画个图理解一下,这个思路确实很巧妙。
Tips:网上有的题解写法是直接判断原图中的度数是否均为偶数,我认为这个是错误的,反例易得,但是似乎可以通过?
xxxxxxxxxx
1551
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22
23
24template < typename T = int >
25inline T read(void);
26
27struct Edge{
28 Edge* nxt;
29 int to;
30 OPNEW;
31}ed[210000];
32ROPNEW(ed);
33Edge* head[11000];
34
35int N, M;
36int deg[11000];
37
38namespace New{
39 int cnt(0);
40 int ddeg[11000];
41 int belong[11000];
42 // basic_string < int > pts[11000];
43 // Edge* head[11000];
44 bitset < 11000 > vis;
45 basic_string < int > ans;
46 // void SetGraph(int p, int idx){
47 // vis[p] = true;
48 // if(deg[p] == 2){belong[p] = ++cnt/*, pts[cnt] += p;*/ return;}
49 // belong[p] = idx;//, pts[idx] += p;
50 // for(auto i = ::head[p]; i; i = i->nxt)
51 // if(!vis[SON])SetGraph(SON, idx);
52 // }
53 void SetAns(int p = 1, bool flag = false){
54 vis[p] = true;
55 for(auto i = ::head[p]; i; i = i->nxt){
56 if(vis[SON])continue;
57 if(flag && belong[SON] == belong[p])SetAns(SON, false);
58 else if((!flag && belong[SON] != belong[p]) || deg[p] == 2)SetAns(SON, true);
59 }ans += p;
60 }
61 void Build(void){
62 for(int i = 1; i <= N; ++i)
63 if(deg[i] > 2 && !vis[i]){//vis[i] = true, SetGraph(i, ++cnt);
64 belong[i] = ++cnt, vis[i] = true;
65 for(auto j = ::head[i]; j; j = j->nxt){
66 if(deg[j->to] == 2)continue;
67 vis[j->to] = true;
68 belong[j->to] = cnt;
69 // pts[cnt] += j->to;
70 }
71 }
72 else if(deg[i] == 2 && !vis[i])vis[i] = true, belong[i] = ++cnt;//, pts[cnt] += i;
73 for(int p = 1; p <= N; ++p)
74 for(auto i = ::head[p]; i; i = i->nxt)
75 if(belong[p] != belong[SON])
76 // printf("from %d to %d, belong : %d -> %d\n", p, SON, belong[p], belong[SON]),
77 ++ddeg[belong[p]], ++ddeg[belong[SON]];
78 // head[belong[p]] = new Edge{head[belong[p]], belong[SON]},
79 // head[belong[SON]] = new Edge{head[belong[SON]], belong[p]};
80 }
81 void Make(void){
82 // int tot(0);
83 // vis.reset();
84 // int cur = 1;
85 // while(true){
86 // vis[cur] = true, ++tot; //ans += cur;//pts[cur];
87 // bool flag(false);
88 // for(auto i = head[cur]; i; i = i->nxt)
89 // if(!vis[SON]){cur = SON, flag = true; break;}
90 // if(!flag)break;
91 // }printf("tot = %d, cnt = %d\n", tot, cnt);
92 // if(tot != cnt)printf("-1\n"), exit(0);
93 // basic_string < int > rans;
94 // for(int i = 1; i <= (int)ans.size(); ++i){
95 // if(i == 1)
96 // }
97 // vis.reset();
98 // for(int i = 1; i <= (int)ans.size(); ++i){
99 // if(vis[i])continue;
100 // vis[i] = true;
101 // if(i == ans.size()){rans += ans.at(i - 1); break;}
102 // bool flag(false);
103 // for(auto j = ::head[ans.at(i - 1)]; j; j = j->nxt)
104 // if(j->to == ans.at(i)){flag = true; break;}
105 // if(flag){rans += ans.at(i - 1); break;}
106 // for(int j = i + 2; j <= (int)ans.size(); ++j){
107 // bool fflag(false);
108 // for(auto k = ::head[ans.at(i - 1)]; k; k = k->nxt)
109 // if(k->to == ans.at(j - 1)){fflag = true; rans += ans.at(j - 1), vis[j] = true; break;}
110 // if(fflag)break;
111 // }
112 // }
113 // for(auto p : ans)printf("%d ", p);
114 // printf("\n");
115 for(int i = 1; i <= cnt; ++i)
116 if((ddeg[i] >> 1) & 1)printf("-1\n"), exit(0);
117 // for(int i = 1; i <= cnt; ++i)printf("ddeg[%d] = %d\n", i, ddeg[i]);
118 vis.reset();
119 SetAns();
120 // if((int)ans.size() != N)printf("-1\n"), exit(0);
121
122 for(auto p : ans)printf("%d ", p);
123 printf("\n");
124 }
125}
126
127int main(){
128 N = read(), M = read();
129 for(int i = 1; i <= M; ++i){
130 int s = read(), t = read();
131 head[s] = new Edge{head[s], t};
132 head[t] = new Edge{head[t], s};
133 ++deg[s], ++deg[t];
134 }
135 New::Build();
136 New::Make();
137 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
138 return 0;
139}
140
141template < typename T >
142inline T read(void){
143 T ret(0);
144 int flag(1);
145 char c = getchar();
146 while(c != '-' && !isdigit(c))c = getchar();
147 if(c == '-')flag = -1, c = getchar();
148 while(isdigit(c)){
149 ret *= 10;
150 ret += int(c - '0');
151 c = getchar();
152 }
153 ret *= flag;
154 return ret;
155}
Patience 游戏。存在有序的 14 个空位,和
Input_1
xxxxxxxxxx
113
Output_1
xxxxxxxxxx
115
Input_2
xxxxxxxxxx
114
Output_2
xxxxxxxxxx
1114
一个显而易见的思路就是
xxxxxxxxxx
471
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25int ans[20] = {0, 1, 2, 5, 14, 47, 189, 891, 4815, 29547, 203173, 1548222, 12966093, 118515434};
26
27int main(){
28 printf("%d\n", ans[read()]);
29 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
30 return 0;
31}
32
33template < typename T >
34inline T read(void){
35 T ret(0);
36 int flag(1);
37 char c = getchar();
38 while(c != '-' && !isdigit(c))c = getchar();
39 if(c == '-')flag = -1, c = getchar();
40 while(isdigit(c)){
41 ret *= 10;
42 ret += int(c - '0');
43 c = getchar();
44 }
45 ret *= flag;
46 return ret;
47}
xxxxxxxxxx
11
xxxxxxxxxx
11
xxxxxxxxxx
11
xxxxxxxxxx
11
xxxxxxxxxx
11
xxxxxxxxxx
11
update-2022_12_16 初稿