【codeforces】【比赛题解】#915 Educational CF Round 36

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

【E】体育课

题意:

震惊,Alex发现自己虽然是个ACMer,但是他还是得参加体育期末考!【多么的讽刺啊……】

Alex要算出自己到期末的\(n\)天中,还有多少天能上体育课?

可惜学校时常更改一段时间的有/无上课的状态,可能把一整段区间都变成不上课或者上课。

你需要算出每一次更改后的答案。\(1\leq n\leq 10^9,1\leq q\leq 3\cdot 10^5\)。

题解:

离散化,线段树,没什么好说的。

 1 #include<algorithm>
 2 #include<cstdio>
 3 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 4 using namespace std;
 5 int n,q;
 6 int x[300001],y[300001],opt[300001];
 7 int sq[600001],cnt;
 8 int siz[600001];
 9 int sz[2097155],dat[2097155],lzy[2097155];
10 void build(int i,int l,int r){
11     if(l==r) {sz[i]=siz[l]; return;}
12     int mid=l+r>>1;
13     build(i<<1,l,mid), build(i<<1|1,mid+1,r);
14     sz[i]=sz[i<<1]+sz[i<<1|1];
15 }
16 void init(){
17     scanf("%d%d",&n,&q);
18     F(i,1,q) scanf("%d%d%d",x+i,y+i,opt+i), sq[++cnt]=x[i]-1, sq[++cnt]=y[i];
19     sort(sq+1,sq+cnt+1);
20     int Cnt=cnt, lst=-1; cnt=0;
21     F(i,1,Cnt) if(sq[i]!=lst) sq[++cnt]=sq[i], lst=sq[i];
22     F(i,1,cnt-1) siz[i]=sq[i+1]-sq[i];
23     F(i,1,q) x[i]=lower_bound(sq+1,sq+cnt+1,x[i]-1)-sq, y[i]=lower_bound(sq+1,sq+cnt+1,y[i])-sq-1;
24     cnt--;
25 }
26 inline void pushdown(int i){
27     if(lzy[i]==1) dat[i<<1]=sz[i<<1], dat[i<<1|1]=sz[i<<1|1], lzy[i<<1]=lzy[i<<1|1]=1;
28     if(lzy[i]==2) dat[i<<1]=dat[i<<1|1]=0, lzy[i<<1]=lzy[i<<1|1]=2;
29     lzy[i]=0;
30 }
31 void M(int a,int b,int i,int l,int r,int typ){
32     if(a<=l&&r<=b) {dat[i]=(typ==1?(sz[i]):0); lzy[i]=typ; return;}
33     if(r<a||b<l) return;
34     pushdown(i);
35     int mid=l+r>>1;
36     M(a,b,i<<1,l,mid,typ), M(a,b,i<<1|1,mid+1,r,typ);
37     dat[i]=dat[i<<1]+dat[i<<1|1];
38 }
39 int main(){
40     init();
41     build(1,1,cnt);
42     F(i,1,q){
43         if(opt[i]==1) M(x[i],y[i],1,1,cnt,1);
44         else M(x[i],y[i],1,1,cnt,2);
45         printf("%d\n",n-dat[1]);
46     }
47     return 0;
48 }

【F】海棠数组树的失衡度

题意:

给你一棵树,节点有权值,计算\(\sum_{i=1}^n\sum_{j=i}^nI(i,j)\)。

\(I(i,j)\)表示\(i\)到\(j\)的路径上的最大点权-最小点权。

题解:

考虑最大最小分开计算,最后最大减最小。

以最大点权为例,如何计算?

假设这个点是\(x\),考虑计算与\(x\)直接或间接联通的点中,到\(x\)的路径中的点权都不比\(x\)大的点。

通过这些点的个数来计算答案。

可以证明,这些点和\(x\)形成的图是一棵树。

我们以\(x\)为根,\(x\)对答案的贡献是\(val_x\cdot[siz_x^2-\sum_{k=x.son}siz_k^2]\)。

那么怎么找到到\(x\)的路径上的点权都不比\(x\)大的点呢?

考虑按照\(val\)为顺序加入点,用并查集维护连通性,就能算答案了。

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 5 #define F2(i,a,b) for(int i=(a);i<(b);++i)
 6 #define dF(i,a,b) for(int i=(a);i>=(b);--i)
 7 #define eF(i,u) for(int i=h[u];i;i=nxt[i])
 8 int n,a[1000001],I[1000001],siz[1000001];
 9 inline bool cmp(int p1,int p2){return a[p1]<a[p2];}
10 int h[1000001],nxt[2000001],to[2000001],tot;
11 inline void ins(int x,int y){nxt[++tot]=h[x];to[tot]=y;h[x]=tot;}
12 bool vis[1000001];
13 int fa[1000001];
14 int ff(int x){return fa[x]?fa[x]=ff(fa[x]):x;}
15 long long ans;
16 int main(){
17     scanf("%d",&n);
18     F(i,1,n) scanf("%d",a+i), I[i]=i;
19     int x,y,u; long long tmp;
20     F2(i,1,n) scanf("%d%d",&x,&y), ins(x,y), ins(y,x);
21     std::sort(I+1,I+n+1,cmp);
22     F(i,1,n){
23         siz[u=I[i]]=1; tmp=0; vis[u]=1;
24         eF(j,u)
25             if(vis[to[j]]) siz[u]+=siz[ff(to[j])], tmp+=1ll*siz[ff(to[j])]*siz[ff(to[j])], fa[ff(to[j])]=u;
26         ans+=a[u]*(1ll*siz[u]*siz[u]-tmp);
27     }
28     memset(fa,0,sizeof fa);
29     dF(i,n,1){
30         siz[u=I[i]]=1; tmp=0; vis[u]=0;
31         eF(j,u)
32             if(!vis[to[j]]) siz[u]+=siz[ff(to[j])], tmp+=1ll*siz[ff(to[j])]*siz[ff(to[j])], fa[ff(to[j])]=u;
33         ans-=a[u]*(1ll*siz[u]*siz[u]-tmp);
34     }
35     printf("%lld",ans>>1);
36     return 0;
37 }

【G】互质数组

题意:

我们说数组\(a\)是互质的,当且仅当\(gcd(a_1,a_2,a_3,\cdots,a_n)=1\)。

给定\(k\),对于每个\(i\;(1\leq i\leq k)\),求出长度为\(n\),且其中元素为\(1\)到\(i\)中的正整数的互质数组的个数。

答案对1000000007取模,再通过玄学的方式算出最终答案。

题解:

容斥+数论(莫比乌斯函数)。

考虑容斥,先计算所有的个数,再扣掉元素是\(2\)的倍数的数组的个数,\(3\)的倍数……

\(4\)的倍数不用扣掉,因为\(2\)已经扣掉过了。

但是\(6\)的倍数被\(2\)和\(3\)扣掉了两遍,要加回来。

对于是\(x\)的倍数,容斥系数就是\(\mu(x)\)——\(x\)的莫比乌斯函数。

对于\(i\)的答案,是\(\sum_{j=1}^{i}\mu(j)(\left\lfloor\frac{i}{j}\right\rfloor)^n\)。

对于每个\(i\),我们使用差分的技巧统计答案。

 1 #include<cstdio>
 2 #define Mod 1000000007
 3 int n,k,Ans;
 4 bool isnprime[2000001]={1,1};
 5 int mobius[2000001]={0,1};
 6 int primes[1000001],pnum;
 7 int ans[2000001];
 8 int pows[2000001];
 9 void Mobius(int num){
10     for(int i=2;i<=num;++i){
11         if(!isnprime[i])
12             primes[++pnum]=i, mobius[i]=-1;
13         for(int j=1;j<=pnum&&i*primes[j]<=num;++j){
14             isnprime[i*primes[j]]=1;
15             if(i%primes[j]==0) break;
16             mobius[i*primes[j]]=-mobius[i];
17         }
18     }
19 }
20 inline int Pow(int base,int exp){
21     int sum=1;
22     while(exp){
23         if(exp&1) sum=(long long)sum*base%Mod;
24         base=(long long)base*base%Mod; exp>>=1;
25     } return sum;
26 }
27 int main(){
28     scanf("%d%d",&n,&k);
29     Mobius(k);
30     pows[0]=0;
31     for(int i=1;i<=k;++i) pows[i]=Pow(i,n);
32     for(int i=1;i<=k;++i){
33         if(!mobius[i]) continue;
34         for(int j=1;j*i<=k;++j){
35             ans[j*i]-=mobius[i]*pows[j-1];
36             ans[j*i]+=mobius[i]*pows[j];
37             ans[j*i]=((ans[j*i]%Mod)+Mod)%Mod;
38         }
39     }
40     for(int i=1;i<=k;++i) ans[i]=(ans[i-1]+ans[i])%Mod, Ans=(Ans+(ans[i]^i))%Mod;
41     printf("%d",Ans);
42     return 0;
43 }

原文地址:https://www.cnblogs.com/PinkRabbit/p/8290384.html

时间: 2024-08-02 12:43:27

【codeforces】【比赛题解】#915 Educational CF Round 36的相关文章

【codeforces】【比赛题解】#849 CF Round #431 (Div.2)

cf的比赛越来越有难度了--至少我做起来是这样. 先看看题目吧:点我. 这次比赛是北京时间21:35开始的,算是比较良心. [A]奇数与结束 "奇数从哪里开始,又在哪里结束?梦想从何处起航,它们又是否会破灭呢?" 给定一个长度为n的序列.确定能不能将序列分成奇数个长度为奇数的非空字串,而且这其中每个子串以奇数开头,以奇数结尾.可以只分成一个(1也是奇数). 输入 第一行一个正整数n,表示序列长度. 第二行n个整数,表示序列中的元素. 输出 输出"Yes"或"

【codeforces】【比赛题解】#854 CF Round #433 (Div.2)

cf一如既往挺丧 看丧题点我! [A]分数 Petya是数学迷,特别是有关于分数的数学.最近他学了所谓一个分数被叫做"真分数"当且仅当其分子小于分母,而一个分数被叫做"最简分数"当且仅当其分子分母互质.在闲暇时间,Petya在用计算器研究:如何把最简真分数转换为小数等问题.有一天他不小心把除号(÷)按成了加号(+),导致他得到了分子与分母的和.Petya想要得到他原来的分数,但他很快发现这不是唯一的.所以现在他想要知道最大的最简真分数使得其分子与分母的和为n. 输入

Educational Codeforces Round 36 (Rated for Div. 2) 题解

Educational Codeforces Round 36 (Rated for Div. 2) 题目的质量很不错(不看题解做不出来,笑 Codeforces 920C 题意 给定一个\(1\)到\(n\)组成的数组,只可以交换某些相邻的位置,问是否可以将数组调整为升序的 解题思路 首先如果每个数都能通过交换到它应该到的位置,那么就可以调整为升序的. 但实际上交换是对称的,如果应该在的位置在当前位置前方的数都交换完成,那么整体就是排好序的,因为不可能所有不在相应位置的数都在相应位置的后方.

[Educational Codeforces Round 36]E. Physical Education Lessons

[Educational Codeforces Round 36]E. Physical Education Lessons <题意概括> 给定一个长度为$N\left(1\leqslant N\leqslant10^{9}\right)$的区间 $Q\left(1\leqslant Q\leqslant3\cdot10^{5}\right)$次将区间$\left[L,R\right]$Set为0或1,每次Set后输出区间总和 <做法> $10_{9}$的范围显然不可能是朴素线段树

Educational Codeforces Round 36

Educational Codeforces Round 36 A. Garden 题目描述:给定\(n\)个数,找出能整除\(m\)的最大的数(假设是\(num\)),输出\(\frac{m}{num}\). solution 枚举. 时间复杂度:\(O(n)\) B. Browser 题目描述:有\(n\)个标签页,当前在第\(i\)页,有下面六个操作: 向左移动一个页面,即\(i-1\) 向右移动一个页面, 即\(i+1\) 关闭左边一个页面,即第\(i-1\)个页面 关闭右边一个页面,即

Educational Codeforces Round 36 (Rated for Div. 2)

Educational Codeforces Round 36 (Rated for Div. 2) F. Imbalance Value of a Tree You are given a tree T consisting of n vertices. A number is written on each vertex; the number written on vertex i is ai. Let's denote the function I(x,?y) as the differ

CF Round 594

CF Round 594(Div1) (A~D)简要题解 开学基本打不了cf了啊.. A Ivan the Fool and the Probability Theory 对于 $ 1 \times n $ 的情况,稍微推一推式子发现是斐波那契数列的两倍(因为第一个位置可以是0可以是1,就是两倍了,否则是一倍). 考虑第一行,第一行有两种情况: 如果第一行是 01010... 交错的,那么 0 开头可以看成一种颜色,1 开头可以看成一种颜色.然后就成了一个竖着的 $ 1 \times n $ 的

CodeForces Dubstep 题解

Vasya works as a DJ in the best Berland nightclub, and he often uses dubstep music in his performance. Recently, he has decided to take a couple of old songs and make dubstep remixes from them. Let's assume that a song consists of some number of word

codeforces Towers 题解

Little Vasya has received a young builder's kit. The kit consists of several wooden bars, the lengths of all of them are known. The bars can be put one on the top of the other if their lengths are the same. Vasya wants to construct the minimal number