DAY 3 QBXT
T1
像个SB题, 不过出了点小锅;
我的思路就是 把一个字符串的答案字符串的长度赋成\(len-1\), 然后每一位都赋成\(a\);
记录一个\(add(len)\) 表示先前出现过多少长度为\(len\) 的不同字符串;
处理当前字符串时, 先从map里扒, 扒不到就把他的答案赋为\(len-1个a\), 然后再加上\(add(len)\);
(在考场上没想到把\(add(len)\) 变为26进制分别加)。。。。。
给的正解是无损压缩(没错我也没听说过);
就是把所有的字符串sort一遍挨个赋\(a, b, c, d, e.....\),
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cstring> #include <map> #define ull unsigned long long const ull base = 2333; using namespace std; map<ull , int> mp; int n, id; struct node { char a[55], ans[55]; int len, id; }e[1005]; int add[55]; void solve(int x) { ull res = 0; for(int i = 1; i <= e[x].len; i ++) res = res * base + e[x].a[i]; if(mp.find(res) != mp.end()) { id = mp[res]; int len = e[x].len - 1; for(int i = 1; i <= len; i ++) e[x].ans[i] = e[id].ans[i]; } else { mp[res] = x; int len = e[x].len - 1; for(int i = 1; i <= len; i ++) e[x].ans[i] = 'a'; int cc = add[len], t = 1; while(cc) { e[x].ans[t] += cc % 26;//emm按26进制算 cc /= 26; t ++; } add[len] ++; } } signed main() { freopen("url.in", "r", stdin); freopen("url.out", "w", stdout); scanf("%d", &n); for(int i = 1; i <= n; i ++) { scanf("%s", e[i].a + 1); e[i].len = strlen(e[i].a + 1); e[i].id = i; } for(int i = 1; i <= n; i ++) solve(i); for(int i = 1; i <= n; i ++) { printf("%s\n", e[i].ans + 1); } return 0; }
T2
当场切掉这个题
把所有的信息读进来后, 记录一下入度;
正常情况下ta是一个根入度为0, 其他入度为1的有向树;
扫一下所有点的入度:
1.找到一个入度为0的点;
此时这个点一定是根(废话)
此时一定对应着某个点的入度为2,找出来那个点和那两个入度边, 枚举删掉哪一个,
然后dfs一遍树, 看成不成立即可
2 .未找到入度为0的点;
也就是没有固定的根, 此时一定有一个环(稍微想一想)
然后把这个环找出来, 然后枚举删掉环上哪一条边 以这条边的to为根dfs判断成不成立即可即可;
成立条件 : 能从根遍利到所有点, 且无环;
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cstring> #include <map> using namespace std; struct node { int u, v, nxt; }e[100005]; int flag, head[100005], cnt, a, b, n, du[100005], uu, vv, ans, tot; bool vis[100005]; void add(int x, int y) { e[++cnt].u = x; e[cnt].v = y; e[cnt].nxt = head[x]; head[x] = cnt; } struct edge { int u, v; }ee[100005]; void dfs(int x) { tot ++; if(flag == 1) return ; vis[x] = 1; for(int i = head[x];i ; i = e[i].nxt) { int to = e[i].v; if(x == uu && to == vv) continue; if(vis[to]) { flag = 1; return ; } dfs(to); } } signed main() { freopen("remove.in", "r", stdin); freopen("remove.out", "w", stdout); scanf("%d" ,&n); for(int i = 1; i <= n; i ++) { scanf("%d%d", &a, &b); add(a, b); ee[i].u = a, ee[i].v = b; du[b] ++; } int rt = 0; for(int i = 1; i <= n; i ++) if(du[i] == 0) rt = i; if(rt != 0) { for(int i = n; i >= 1; i --) { if(du[ee[i].v] != 2) continue; else { for(int j = 1; j <= n; j ++) vis[j] = 0; uu = ee[i].u; vv = ee[i].v; flag = 0; tot = 0; dfs(rt); if(!flag&&tot == n) { ans = i;break; } } } } else { for(int i = n; i >= 1; i --) { for(int j = 1; j <= n; j ++) vis[j] = 0; uu = ee[i].u; vv = ee[i].v; flag = 0; tot = 0; dfs(ee[i].v); if(!flag&&tot == n) { ans = i;break; } } } printf("%d", ans); return 0; }
T3
啥都别说概率Dp
易得k没啥用
so, n = n/k 上取整, k = 1;
设\(f(i, j)\)表示A 还有\(i\), 吨未倒, B还有\(j\)吨未倒时的答案(概率);
则\(f(i, 0)=0.0\) \(f(0, j)=1.0\) \(f(0, 0) = 0.5\)
\(f(i, j) = (f(i-1, j-3)+f(i-2, j-2)+f(i-3,j-1)+f(i-4,j))*0.25\)
\(f(n, n)\) 就是答案;
由打表易得当n > 某个数 时 \(ans = 1.0\)
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cstring> #include <map> using namespace std; int n, k, o; double f[10000][10100]; signed main() { freopen("tea.in", "r", stdin); freopen("tea.out", "w", stdout); scanf("%d%d", &n, &k); if(n%k!=0) o = 1; n /= k; n += o; if(n >= 200) {printf("1.000000"); return 0;} f[0][0] = 0.5; for(int i = 1; i <= n; i ++) f[i][0] = 0.0; for(int i = 1; i <= n; i ++) f[0][i] = 1.0; for(int i = 1; i <= n; i ++) for(int j = 1; j <= n; j ++) f[i][j] = 0.25 * (f[max(i-1, 0)][max(j-3, 0)] + f[max(i-2, 0)][max(j-2, 0)] + f[max(i-3, 0)][max(j-1, 0)] + f[max(i-4, 0)][j]); printf("%.6f", f[n][n]); return 0; }