10.11 模拟赛(QBXT国庆Day3)
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 > 235\) 时 \(ans = 1.0\) 所以不用怕dp数组空间复杂度
#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 >= 235) {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;
}