2021.9.1
T1:网址压缩
Problem:
网址压缩的目标是希望将较长的网址变为更短的网址。我们现在的任务是给定𝑁个只包含小写字母的字符串,你需要输出对这𝑁个字符串进行压缩的结果。你可以使用任意的压缩算法,但你需要保证满足如下的性质:
1、压缩的结果字符串仍然只有小写字母。
2、压缩的结果不能是空串,且长度必须要比原来的字符串短。
3、相同的字符串压缩结果必须相同,不同的字符串压缩结果必须不同。
任意满足上述条件的压缩方法都是正确的,所以你的目标就是对给定的𝑁个字符串进行压缩。数据保证有解。
Solution:
随机替换字符串
Code:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<map> 5 #include<string> 6 #include<iostream> 7 #include<algorithm> 8 using namespace std; 9 const int maxn=1010; 10 map<string,string> ma; 11 string z[maxn]; 12 int n,l=1,res[233],y[maxn]; 13 bool cmp(int a,int b){ 14 return z[a]<z[b]; 15 } 16 int main(){ 17 cin>>n; 18 for(int a=1;a<=n;a++){ 19 cin>>z[a]; 20 y[a]=a; 21 } 22 res[1]=1; 23 sort(y+1,y+n+1,cmp); 24 for(int a=1;a<=n;a++){ 25 string now=z[y[a]]; 26 if(ma.count(now)!=0) ; 27 else{ 28 string cur = ""; 29 for(int a=l;a>=1;a--) 30 cur=cur+(char)(res[a]+'a'-1); 31 ma[now]=cur; 32 res[1]++; 33 for(int a=1;a<=l;a++) 34 if(res[a]>26){ 35 res[a]=1; 36 res[a+1]++; 37 } 38 if(res[l+1]) l++; 39 } 40 } 41 for(int a=1;a<=n;a++) 42 cout<<ma[z[a]]<<endl; 43 return 0; 44 }
T2:异构体
Problem:
Paradeus 是一个新兴的宗教组织,该组织包含了𝑁 − 1个 Nyto,以及一个Mercurows 总共𝑁个人组成。每个 Nyto 都是被其他某个人传教而进入的 Paradeus,而 Mercurows 是宗教的创立者,也就是说 Mercurows 并没有被任何人拉进组织。
不法分子在 Paradeus 的教义上添加了一条记录(𝑎, 𝑏),代表𝑏是由𝑎介绍入教的。
现在给定𝑁对记录(𝑎𝑖, 𝑏𝑖)代表是𝑎𝑖将𝑏𝑖拉入教的。注意这𝑁条记录包含了被不法分子添加的那一条。现在我们希望你找到某一条记录,使得删掉这条记录之后剩下的𝑁 − 1条记录能够形成合法的教义。要注意的是,教义并没有标注谁是 Mercurows,所以任何人都有可能是 Mercurows。
Solution:
1.找环
2.找入度为2的点
Code:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=100010; 7 int n,en,head,tail,in[maxn],ex[maxn][2],q[maxn],f[maxn],pre[maxn][2]; 8 bool use[maxn]; 9 struct edge{ 10 int s,e,p; 11 edge *next; 12 }*v[maxn],ed[maxn]; 13 void add_edge(int s,int e,int p){ 14 en++; 15 ed[en].next=v[s]; 16 v[s]=ed+en; 17 v[s]->e=e; 18 v[s]->p=p; 19 in[e]++; 20 ex[en][0]=s; 21 ex[en][1]=e; 22 } 23 int get(int p){ 24 if (f[p]==p) return p; 25 else return get(f[p]); 26 } 27 void init(){ 28 en=0; 29 memset(v,0,sizeof(v)); 30 memset(in,0,sizeof(in)); 31 } 32 void read(){ 33 scanf("%d",&n); 34 for(int a=1;a<=n;a++){ 35 int s,e; 36 scanf("%d%d",&s,&e); 37 add_edge(s,e,a); 38 } 39 } 40 bool work1(int p,int d){ 41 memset(use,false,sizeof(use)); 42 use[p]=true; 43 head=tail=1; 44 q[1]=p; 45 for(;head<=tail;){ 46 int p=q[head++]; 47 for(edge *e=v[p];e;e=e->next) 48 if(e->p!=d){ 49 if(use[e->e]) return false; 50 use[e->e]=true; 51 pre[e->e][0]=p; 52 pre[e->e][1]=e->p; 53 q[++tail]=e->e; 54 } 55 } 56 for(int a=1;a<=n;a++) 57 if(!use[a]) return false; 58 return true; 59 } 60 int work2(int p){ 61 memset(use,false,sizeof(use)); 62 use[p]=true; 63 head=tail=1; 64 q[1]=p; 65 for(;head<=tail;){ 66 int p=q[head++]; 67 for(edge *e=v[p];e;e=e->next){ 68 if(use[e->e]) return e->p; 69 use[e->e]=true; 70 q[++tail]=e->e; 71 } 72 } 73 return -1; 74 } 75 int work(){ 76 for(int a=1;a<=n;a++) 77 if(in[a]==2){ 78 int p1=-1,p2=-1; 79 for(int b=1;b<=n;b++) 80 if(ex[b][1]==a){ 81 if(p1==-1) p1=b; 82 else p2=b; 83 } 84 if(p1>p2) swap(p1,p2); 85 for(int b=1;b<=n;b++) 86 if(in[b]==0){ 87 if(work1(b,p2)) return p2; 88 else return p1; 89 } 90 } 91 for(int a=1;a<=n;a++) 92 if(in[a]==0) return work2(a); 93 for(int a=1;a<=n;a++) 94 f[a]=a; 95 for(int a=1;a<=n;a++){ 96 int f1=get(ex[a][0]); 97 int f2=get(ex[a][1]); 98 if(f1==f2){ 99 work1(ex[a][1],a); 100 int p=ex[a][1],ans=a; 101 while(p!=ex[a][1]){ 102 ans=max(ans,pre[p][1]); 103 p=pre[p][0]; 104 } 105 return ans; 106 } 107 f[f1]=f2; 108 } 109 return -1; 110 } 111 int main(){ 112 init(); 113 read(); 114 int p=work(); 115 printf("%d\n",p); 116 return 0; 117 }
T3:给大佬递茶
Problem:
一开始Alice 和 Bob 都有一个杯子里面装了𝑁吨的茶。现在每次 Alice 会等概率地随机向垃圾桶里面倒入4𝐾, 3𝐾, 2𝐾或者𝐾吨的茶,并且如果 Alice 倒了𝑥吨的茶,Bob 就会向垃圾桶里面导入4𝐾 − 𝑥吨的茶。注意每次操作的时候 Alice 或者 Bob 的茶有可能不够多,这个时候就能倒多少到多少。现在问 Alice 在四种操作完全等概率的情况下,Alice 先把自己的茶倒光的概率加上 Alice 和 Bob 同时把茶倒光的概率的一半是多少。注意,Alice 和 Bob 每轮倒茶都是同时开始同时结束。
Solution:
DP+找规律
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e3+100; 4 const int mod=1e9+7; 5 int n,k; 6 double ans; 7 double dp[N][N]; 8 inline int read(){ 9 int x=0,f=1; 10 char ch=getchar(); 11 while(ch<'0'||ch>'9'){ 12 if(ch=='-') f=-1; 13 ch=getchar(); 14 } 15 while(ch>='0'&&ch<='9'){ 16 x=(x<<1)+(x<<3)+(ch^48); 17 ch=getchar(); 18 } 19 return x*f; 20 } 21 int main() { 22 n=read(); 23 k=read(); 24 n=ceil((n*1.0)/(k*1.0)); 25 k=1; 26 if(n>=235){ 27 cout<<"1.000000"<<endl; 28 return 0; 29 } 30 dp[n][n]=1.0; 31 for(int i=n;i>=1;i--){ 32 for(int j=n;j>=1;j--){ 33 for(int p=1;p<=4;p++){ 34 int x=max(0,i-k*p); 35 int y=max(0,j-k*(4-p)); 36 dp[x][y]+=dp[i][j]*0.25; 37 } 38 } 39 } 40 for(int i=1;i<=n;i++){ 41 ans+=dp[0][i]; 42 } 43 ans+=dp[0][0]*0.5; 44 printf("%0.6f\n",ans); 45 fclose(stdin); 46 fclose(stdout); 47 return 0; 48 }

浙公网安备 33010602011771号