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
xxxxxxxxxx113 0
难度不高,但细节颇多。
不难想到数据范围较小,可以枚举区间内的所有横坐标,然后通过斜率和分类讨论计算横坐标对应的纵坐标的数量和范围,找到对应的方格即可。同时不难想到若
x123
45678910
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
222324
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
xxxxxxxxxx115 5 3
Output_1
xxxxxxxxxx310.00000 3.000002-4.00000 0.0000034.00000 0.00000
首先不难想到该三角形可以任意平移,所以考虑固定点
不难发现方程非线性,可解,仅需额外判断是否有解即可。
仍需注意一个额外的细节,判断无解时需要和
xxxxxxxxxx57123
45678910
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
2223
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
xxxxxxxxxx212210 10
Output_1
xxxxxxxxxx1150 50
钦定均为向下取整,令钦定后的和为
xxxxxxxxxx58123
45678910
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
xxxxxxxxxx31125 332 3 5
Output_1
xxxxxxxxxx11SECOND PLAYER MUST WIN
一道挺好的博弈论的题。
对于这种类型题不难想到
转移显然,即考虑是否所有子状态均为必胜,是则此状态必输,反之必胜。
发现这个的复杂度是
xxxxxxxxxx70123
45678910
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
xxxxxxxxxx112
Output_1
xxxxxxxxxx1110
简单数论,经典套路。
显然从式子里拆出来
显然
具体式子显然为:
注意:需要特判
xxxxxxxxxx62123
45678910
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
xxxxxxxxxx81725 432 243 950 561 376 684 11
Output_1
xxxxxxxxxx81YES22 3 630 5 141 0 755 0 062 4 071 0 083 0 0
笛卡尔树模板,处理好各种映射之间的关系即可。
xxxxxxxxxx74123
45678910
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
xxxxxxxxxx214 421 2 2 3 3 4 4 1
Output_1
xxxxxxxxxx111 2 3 4
Input_2
xxxxxxxxxx319 1221 2 2 3 3 1 1 4 2 5 3 634 7 5 8 6 9 7 8 8 9 9 7
Output_2
xxxxxxxxxx11-1
一道十分高妙的题,思路不难但是构造方案还是需要亿些细节的。
首先根据题意,若
如果按照一般的构造欧拉回路的思路,我们会发现将欧拉回路还原回哈密尔顿回路是复杂的,因为我们是需要考虑缩完的两个点之间的边在原图中是哪些点,似乎可以维护但极为复杂,细节过多,所以这里有一个特别高妙的做法。
可以参考代码中 SetAns 函数,如此实现是可以保证,对于缩点后的没有连向其它新图中的点的旧点,当遍历到其之后就不会接着遍历,然后直接记录,反之则会继续找到新的点。可以画个图理解一下,这个思路确实很巧妙。
Tips:网上有的题解写法是直接判断原图中的度数是否均为偶数,我认为这个是错误的,反例易得,但是似乎可以通过?
xxxxxxxxxx155123
45678910
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
xxxxxxxxxx113
Output_1
xxxxxxxxxx115
Input_2
xxxxxxxxxx114
Output_2
xxxxxxxxxx1114
一个显而易见的思路就是
xxxxxxxxxx47123
45678910
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}
xxxxxxxxxx11
xxxxxxxxxx11
xxxxxxxxxx11
xxxxxxxxxx11
xxxxxxxxxx11
xxxxxxxxxx11
update-2022_12_16 初稿