虽然最近打了很多场CF,也涨了很多分,但是好久没写CF的题解了。
前几次刚刚紫名的CF,太伤感情了,一下子就掉下来了,不懂你们Div.1。
珂学的那场我只做了第一题……悲伤。
这次的Educational Round打的还可以,虽然吧没有涨分(因为我是紫色的啊)。
做了前4题,后面3题也比较简单,陆续也做完了。
所以心情好,来写一篇题解!
【A】花园
题意:
长度为\(k\)的线段,用若干个长度为\(a_i\)的线段,正好覆盖。(\(a_i|k\))
给定\(n\)个\(a_i\),求出最小的\(k/a_i\),前提是\(a_i|k\)。
题解:
大模拟。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<string> 5 #include<cstdio> 6 #include<vector> 7 #include<queue> 8 #include<cmath> 9 #include<set> 10 #include<map> 11 #define ll long long 12 #define F(i,a,b) for(int i=(a);i<=(b);++i) 13 #define F2(i,a,b) for(int i=(a);i<(b);++i) 14 #define dF(i,a,b) for(int i=(a);i>=(b);--i) 15 #define dF2(i,a,b) for(int i=(a);i>(b);--i) 16 #define eF(i,u) for(int i=h[u];i;i=nxt[i]) 17 using namespace std; 18 const int INF=0x3f3f3f3f; 19 inline int Gcd(int X,int Y){return Y?Gcd(Y,X%Y):X;} 20 inline int Max(int X,int Y){return X<Y?Y:X;} 21 inline int Min(int X,int Y){return X<Y?X:Y;} 22 inline ll Max(ll X,ll Y){return X<Y?Y:X;} 23 inline ll Min(ll X,ll Y){return X<Y?X:Y;} 24 int n,k,x; 25 int ans=100000000; 26 int main(){ 27 scanf("%d%d",&n,&k); 28 while(n--) {scanf("%d",&x); if(k%x==0) ans=Min(ans,k/x);} 29 printf("%d",ans); 30 return 0; 31 }
【B】浏览器
题意:
看样例解释猜题意。
对于浏览器顶部的标签,你有这样的操作:关闭这个标签左/右侧的所有标签,把鼠标移到左/右一个标签。
给定标签数目\(n\),鼠标现在所在的标签\(p\),问你留下标签区间\([l,r]\)的最少操作次数。
题解:
大模拟,注意看左边/右边到底有没有标签。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<string> 5 #include<cstdio> 6 #include<vector> 7 #include<queue> 8 #include<cmath> 9 #include<set> 10 #include<map> 11 #define ll long long 12 #define F(i,a,b) for(int i=(a);i<=(b);++i) 13 #define F2(i,a,b) for(int i=(a);i<(b);++i) 14 #define dF(i,a,b) for(int i=(a);i>=(b);--i) 15 #define dF2(i,a,b) for(int i=(a);i>(b);--i) 16 #define eF(i,u) for(int i=h[u];i;i=nxt[i]) 17 using namespace std; 18 const int INF=0x3f3f3f3f; 19 inline int Gcd(int X,int Y){return Y?Gcd(Y,X%Y):X;} 20 inline int Max(int X,int Y){return X<Y?Y:X;} 21 inline int Min(int X,int Y){return X<Y?X:Y;} 22 inline ll Max(ll X,ll Y){return X<Y?Y:X;} 23 inline ll Min(ll X,ll Y){return X<Y?X:Y;} 24 inline int Abs(int X){return X<0?-X:X;} 25 int n,p,l,r; 26 int main(){ 27 scanf("%d%d%d%d",&n,&p,&l,&r); 28 if(l==1&&r==n){puts("0");return 0;} 29 if(l==1){printf("%d",Abs(p-r)+1);return 0;} 30 if(r==n){printf("%d",Abs(p-l)+1);return 0;} 31 printf("%d",Min(Abs(p-r),Abs(p-l))+r-l+2); 32 return 0; 33 }
【C】数位重排
题意:
给定两个数\(a,b\),求出把\(a\)在十进制下数位重排后不超过\(b\)的最大数,不能有前导零。
题解:
暴力DFS。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<string> 5 #include<cstdio> 6 #include<vector> 7 #include<queue> 8 #include<cmath> 9 #include<set> 10 #include<map> 11 #define ll long long 12 #define F(i,a,b) for(int i=(a);i<=(b);++i) 13 #define F2(i,a,b) for(int i=(a);i<(b);++i) 14 #define dF(i,a,b) for(int i=(a);i>=(b);--i) 15 #define dF2(i,a,b) for(int i=(a);i>(b);--i) 16 #define eF(i,u) for(int i=h[u];i;i=nxt[i]) 17 using namespace std; 18 const int INF=0x3f3f3f3f; 19 inline int Gcd(int X,int Y){return Y?Gcd(Y,X%Y):X;} 20 inline int Max(int X,int Y){return X<Y?Y:X;} 21 inline int Min(int X,int Y){return X<Y?X:Y;} 22 inline ll Max(ll X,ll Y){return X<Y?Y:X;} 23 inline ll Min(ll X,ll Y){return X<Y?X:Y;} 24 ll a,b,aa,bb; 25 int ca,cb; 26 int oo; 27 int use[10]; 28 int bs[20]; 29 int cs[20]; 30 void print(){ 31 oo=1; 32 // puts("!!"); 33 for(int i=ca;i>=1;--i) printf("%d",cs[i]); 34 } 35 void dfs(int stp,bool deng){ 36 if(stp==0) {print(); return;} 37 if(oo) return; 38 for(int i=deng?bs[stp]:9;i>=0;--i){ 39 if(stp==ca&&i==0) continue; 40 if(!use[i]) continue; 41 use[i]--; cs[stp]=i; 42 dfs(stp-1,deng?(i==bs[stp]):0); 43 use[i]++; 44 } 45 } 46 int main(){ 47 scanf("%lld%lld",&a,&b); aa=a,bb=b; 48 while(aa) use[aa%10]++,aa/=10,++ca; while(bb) bs[cb+1]=bb%10,bb/=10,++cb; 49 if(cb>ca){ 50 for(int i=9;i>=0;--i) while(use[i]) use[i]--,printf("%d",i); 51 return 0; 52 } 53 dfs(ca,1); 54 return 0; 55 }
【D】几乎无环图
题意:
给定一个有向图,问能否删掉一条边后,这个图变成无环图。\(2\leq n\leq 500,1\leq m\leq min(n(n-1),1000000)\)
题解:
先找到一个环(找不到就YES)。
找环用DFS/拓扑排序,我写的时候脑子不好,用了恶心的DFS。
这个环上最多\(n\)条边,对每条边都试一次,看看还有没有环。
为什么要先找到一个环?
拓扑排序/DFS的复杂度是\(O(n+m)\)的。
那么如果直接对每条边试着删除的话,总复杂度\(O((n+m)^2)\),就T飞了。
先找到一个环的话,总复杂度\(O(n(n+m))\),能过。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<string> 5 #include<cstdio> 6 #include<vector> 7 #include<queue> 8 #include<cmath> 9 #include<set> 10 #include<map> 11 #define ll long long 12 #define F(i,a,b) for(int i=(a);i<=(b);++i) 13 #define F2(i,a,b) for(int i=(a);i<(b);++i) 14 #define dF(i,a,b) for(int i=(a);i>=(b);--i) 15 #define dF2(i,a,b) for(int i=(a);i>(b);--i) 16 #define eF(i,u) for(int i=h[u];i;i=nxt[i]) 17 using namespace std; 18 const int INF=0x3f3f3f3f; 19 inline int Gcd(int X,int Y){return Y?Gcd(Y,X%Y):X;} 20 inline int Max(int X,int Y){return X<Y?Y:X;} 21 inline int Min(int X,int Y){return X<Y?X:Y;} 22 inline ll Max(ll X,ll Y){return X<Y?Y:X;} 23 inline ll Min(ll X,ll Y){return X<Y?X:Y;} 24 int n,m; 25 int h[501],nxt[100001],to[100001],tot; 26 inline void ins(int x,int y){nxt[++tot]=h[x];to[tot]=y;h[x]=tot;} 27 int used[501],ret[501]; 28 int o,oo,ooo; 29 int stk[501],top,pos[501]; 30 int fk[501][501]; 31 bool use[100001]; 32 int cnt; 33 void dfs(int u){ 34 // printf(" u: %d\n",u); 35 used[u]=cnt; stk[++top]=u; pos[u]=top; 36 eF(i,u){ 37 if(used[to[i]]==0) dfs(to[i]); 38 else{if(used[to[i]]==cnt&&ret[to[i]]==0){/*printf("error : %d -> %d\n",u,to[i]);*/o=pos[to[i]]; return;}} 39 if(o) return; 40 } --top; ret[u]=1; 41 } 42 void dfs2(int u){ 43 // printf(" u: %d\n",u); 44 used[u]=cnt; 45 eF(i,u) if(!use[i]){ 46 // printf("%d -> %d\n",u,to[i]); 47 if(used[to[i]]==0) dfs2(to[i]); 48 else{if(used[to[i]]==cnt&&ret[to[i]]==0){/*printf("error : %d -> %d\n",u,to[i]);*/ooo=1; return;}} 49 if(ooo) return; 50 } ret[u]=1; 51 } 52 int main(){ 53 scanf("%d%d",&n,&m); 54 if(m-1>n*(n-1)/2) {puts("NO"); return 0;} 55 if(m<=2) {puts("YES"); return 0;} 56 int x,y; 57 F(i,1,m) scanf("%d%d",&x,&y), ins(x,y), fk[x][y]=tot; 58 F(i,1,n){ 59 o=0; top=0; cnt=i; 60 if(!used[i]) dfs(i); 61 if(o) {oo=1; break;} 62 } 63 if(!oo) {puts("YES"); return 0;} 64 // F(i,o,top) 65 // printf(",%d",stk[i]); puts(""); 66 F(i,o,top){ 67 // printf(" %d\n",stk[i]); 68 memset(used,0,sizeof used); 69 memset(ret,0,sizeof ret); 70 ooo=0; 71 if(i!=top) use[fk[stk[i]][stk[i+1]]]=1; 72 else use[fk[stk[i]][stk[o]]]=1; 73 F(j,1,n){ 74 cnt=j; 75 if(used[j]==0) dfs2(j); 76 // printf("%d %d %d\n",j,used[j],ooo); 77 // puts("===="); 78 if(ooo) break; 79 } 80 if(!ooo) {puts("YES"); return 0;} 81 if(i!=top) use[fk[stk[i]][stk[i+1]]]=0; 82 else use[fk[stk[i]][stk[o]]]=0; 83 } puts("NO"); 84 return 0; 85 }