考的还是比较炸的,前两道已经想的差不多了,不过最后还是挂了。。
#6178. 「美团 CodeM 初赛 Round B」景区路线规划。
签到题,随便设一下状态转移一下即可,然后我大概就是想了很久总觉得这个玩意不符合无后效性,于是写了个十分复杂的分步考虑互相转移两个 DP 分别搞,一个是从该点起始再回到该点恰好时间的概率,然后再转移互相之间的概率,很 nt 的思路,甚至后面的互相转移的过程就是答案的式子,麻了麻了。
最后不知道时正确性的问题还是什么,总之只有
xxxxxxxxxx
1061
2
3
4
5
6
7
8
9
10
11
12using namespace std;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23
24
25template < typename T = int >
26inline T read(void);
27
28struct Edge{
29 Edge* nxt;
30 int to;
31 int val;
32 OPNEW;
33}ed[26000];
34ROPNEW;
35Edge* head[110];
36
37int N, M, K;
38int c[110], h1[110], h2[110];
39int deg[110][500];
40ld expA(0.0), expB(0.0);
41ld dp[110][500];
42ld rdp[110][500];
43
44int main(){
45 freopen("park.in", "r", stdin);
46 freopen("park.out", "w", stdout);
47 N = read(), M = read(), K = read();
48 for(int i = 1; i <= N; ++i)c[i] = read(), h1[i] = read(), h2[i] = read();
49 for(int i = 1; i <= M; ++i){
50 int s = read(), t = read(), v = read();
51 head[s] = new Edge{head[s], t, v};
52 head[t] = new Edge{head[t], s, v};
53 }
54 for(int p = 1; p <= N; ++p)
55 for(int j = 0; j <= K; ++j)
56 for(auto i = head[p]; i; i = i->nxt)
57 if(j + i->val + c[SON] <= K)++deg[p][j];
58 for(int p = 1; p <= N; ++p){
59 dp[p][c[p]] = 1.0 / (ld)N;
60 for(int cost = 0; cost <= K; ++cost)
61 for(auto i = head[p]; i; i = i->nxt)
62 if(deg[p][cost] && deg[SON][cost + i->val + c[SON]] && cost + i->val * 2 + c[SON] + c[p] <= K)
63 dp[p][cost + i->val * 2 + c[SON] + c[p]] += dp[p][cost] * (1.0 / (ld)deg[p][cost]) * (1.0 / (ld)deg[SON][cost + i->val + c[SON]]);
64 }
65 memcpy(rdp, dp, sizeof dp);
66 for(int p = 1; p <= N; ++p)
67 for(int j = 0; j <= K; ++j)
68 for(auto i = head[p]; i; i = i->nxt)
69 if(deg[p][j] && j + i->val + c[SON] <= K)
70 rdp[SON][j + i->val + c[SON]] += dp[p][j] * (1.0 / (ld)deg[p][j]);
71 for(int i = 1; i <= N; ++i)
72 for(int j = 0; j <= K; ++j)
73 // printf("dp[%d][%d] = %.5Lf, rdp[%d][%d] = %.5Lf\n", i, j, dp[i][j], i, j, rdp[i][j]),
74 expA += (ld)h1[i] * rdp[i][j], expB += (ld)h2[i] * rdp[i][j];
75 printf("%.5Lf %.5Lf\n", expA, expB);
76 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
77 return 0;
78}
79
80template < typename T >
81inline T read(void){
82 T ret(0);
83 int flag(1);
84 char c = getchar();
85 while(c != '-' && !isdigit(c))c = getchar();
86 if(c == '-')flag = -1, c = getchar();
87 while(isdigit(c)){
88 ret *= 10;
89 ret += int(c - '0');
90 c = getchar();
91 }
92 ret *= flag;
93 return ret;
94}
95/*
965 4 60
9725 12 83
9830 38 90
9916 13 70
10022 15 63
10150 72 18
1022 1 7
1033 1 7
1044 3 1
1055 3 10
106*/
想到随机权值,想到哈希,然后考虑将其划分集合之后作个差直接在每个数的随机权值构成的 unordered_set
里查一下,然后想到这东西可能不是差一个数,于是就寄了,也想过直接前缀异或然后二分,但是判不了个数,也想过前缀哈希,但是判不了顺序。
所以最后挂了个暴力上去,
xxxxxxxxxx
781
2
3
4
5
6
7
8
9
10
11
12using namespace std;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23template < typename T = int >
24inline T read(void);
25
26int N, Q;
27basic_string < int > A;
28
29int main(){
30 freopen("sequence.in", "r", stdin);
31 freopen("sequence.out", "w", stdout);
32 int T = read();
33 while(T--){
34 A.clear(); A += -1;
35 N = read(), Q = read();
36 for(int i = 1; i <= N; ++i)A += read();
37 while(Q--){
38 int a = read(), b = read(), c = read(), d = read();
39 basic_string < int > s1(A.substr(a, b - a + 1)), s2(A.substr(c, d - c + 1));
40 sort(s1.begin(), s1.end()), sort(s2.begin(), s2.end());
41 bool diff(false);
42 for(int i = 0; i < (int)s1.size(); ++i){
43 if(s1.at(i) != s2.at(i)){
44 if(!diff)diff = true;
45 else{printf("NO\n"); break;}
46 }
47 if(i == (int)s1.size() - 1)printf("YES\n");
48 }
49 }
50 }
51 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
52 return 0;
53}
54
55template < typename T >
56inline T read(void){
57 T ret(0);
58 int flag(1);
59 char c = getchar();
60 while(c != '-' && !isdigit(c))c = getchar();
61 if(c == '-')flag = -1, c = getchar();
62 while(isdigit(c)){
63 ret *= 10;
64 ret += int(c - '0');
65 c = getchar();
66 }
67 ret *= flag;
68 return ret;
69}
70
71/*
721
736 3
741 3 4 2 3 4
751 3 4 6
761 2 5 6
773 5 2 4
78*/
这个 OJ 挂了,所以链接也没用了。
给定无向带权完全图,等概率随机生成树,求任意两点间路径长度期望。
部分分很足,详细推导后可以拿到
如上所说,将多出来的转移删掉然后先枚举时间再枚举点,就可以直接消除后效性了。
xxxxxxxxxx
1101
2
3
4
5
6
7
8
9
10
11
12using namespace std;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23
24
25template < typename T = int >
26inline T read(void);
27
28struct Edge{
29 Edge* nxt;
30 int to;
31 int val;
32 OPNEW;
33}ed[26000];
34ROPNEW;
35Edge* head[110];
36
37int N, M, K;
38int c[110], h1[110], h2[110];
39int deg[110][500];
40ld expA(0.0), expB(0.0);
41ld dp[110][500];
42ld rdp[110][500];
43
44int main(){
45 // freopen("park.in", "r", stdin);
46 // freopen("park.out", "w", stdout);
47 N = read(), M = read(), K = read();
48 for(int i = 1; i <= N; ++i)c[i] = read(), h1[i] = read(), h2[i] = read();
49 for(int i = 1; i <= M; ++i){
50 int s = read(), t = read(), v = read();
51 head[s] = new Edge{head[s], t, v};
52 head[t] = new Edge{head[t], s, v};
53 }
54 for(int p = 1; p <= N; ++p)
55 for(int j = 0; j <= K; ++j)
56 for(auto i = head[p]; i; i = i->nxt)
57 if(j + i->val + c[SON] <= K)++deg[p][j];
58 // for(int p = 1; p <= N; ++p){
59 // dp[p][c[p]] = 1.0 / (ld)N;
60 // for(int cost = 0; cost <= K; ++cost)
61 // for(auto i = head[p]; i; i = i->nxt)
62 // if(deg[p][cost] && deg[SON][cost + i->val + c[SON]] && cost + i->val * 2 + c[SON] + c[p] <= K)
63 // dp[p][cost + i->val * 2 + c[SON] + c[p]] += dp[p][cost] * (1.0 / (ld)deg[p][cost]) * (1.0 / (ld)deg[SON][cost + i->val + c[SON]]);
64 // }
65 // memcpy(rdp, dp, sizeof dp);
66 for(int i = 1; i <= N; ++i)rdp[i][c[i]] = 1.0 / (ld)N;
67 for(int j = 0; j <= K; ++j)
68 for(int p = 1; p <= N; ++p){
69 // rdp[p][c[p]] = 1.0 / (ld)N;
70
71 for(auto i = head[p]; i; i = i->nxt)
72 if(deg[p][j] && j + i->val + c[SON] <= K)
73 rdp[SON][j + i->val + c[SON]] += rdp[p][j] * (1.0 / (ld)deg[p][j]);
74 }
75 for(int i = 1; i <= N; ++i)
76 for(int j = 0; j <= K; ++j)
77 // printf("dp[%d][%d] = %.5Lf, rdp[%d][%d] = %.5Lf\n", i, j, dp[i][j], i, j, rdp[i][j]),
78 expA += (ld)h1[i] * rdp[i][j], expB += (ld)h2[i] * rdp[i][j];
79 printf("%.5Lf %.5Lf\n", expA, expB);
80 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
81 return 0;
82}
83
84template < typename T >
85inline T read(void){
86 T ret(0);
87 int flag(1);
88 char c = getchar();
89 while(c != '-' && !isdigit(c))c = getchar();
90 if(c == '-')flag = -1, c = getchar();
91 while(isdigit(c)){
92 ret *= 10;
93 ret += int(c - '0');
94 c = getchar();
95 }
96 ret *= flag;
97 return ret;
98}
99/*
1005 4 60
10125 12 83
10230 38 90
10316 13 70
10422 15 63
10550 72 18
1062 1 7
1073 1 7
1084 3 1
1095 3 10
110*/
(权值、动态开点)主席树维护和哈希即可,这样就可以快速处理无序哈希,很朴素的思路,当然我是 sb 所以没想到。
code 懒得补了,主要欠的题太多,以后复习主席树的时候或许再来写写
代码咕了。
update-2023_02_11 初稿