虽然最近打了很多场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 }
View Code

相关文章: