Educational Codeforces Round 64 (Rated for Div. 2) A,B,C,D,E,F
比赛链接:
https://codeforces.com/contest/1156
A. Inscribed Figures
题意:
给出$n(2\leq n\leq 100)$个数,只含有1,2,3,分别代表圆,高与底相等的三角形,正方形
$a_{i+1}$在$a_{i}$的里面,$a_{i+1}$的面积尽可能的大
求不同的交点个数
分析:
注意正方形里面一个圆,再里面一个三角形的时候,有一个交点重合
ac代码:
- #include<bits/stdc++.h>
- #define ll long long
- using namespace std;
- const int maxn=1e5+10;
- const int maxm=200000*2+10;
- const int mod=1e9+7;
- int num[maxn];
- ll ans;
- int main()
- {
- int n;
- scanf("%d",&n);
- for(int i=1;i<=n;i++)
- scanf("%d",&num[i]);
- for(int i=2;i<=n;i++)
- {
- if(num[i]==1)
- {
- if(num[i-1]==2)ans+=3;
- if(num[i-1]==3)ans+=4;
- }
- if(num[i]==2)
- {
- if(num[i-1]==1)
- {
- if(i-2>=1&&num[i-2]==3)
- ans+=2;
- else ans+=3;
- }
- if(num[i-1]==3)ans=1e18;
- }
- if(num[i]==3)
- {
- if(num[i-1]==1)ans+=4;
- if(num[i-1]==2)ans=1e18;
- }
- }
- if(ans>=1e17)
- cout<<"Infinite"<<endl;
- else
- {
- cout<<"Finite"<<endl;
- cout<<ans<<endl;
- }
- return 0;
- }
B. Ugly Pairs
题意:
给出一个字符串$s(1\leq |s|\leq 100)$,重排它们,让每对相邻的字符在$ascii$表中不相邻
分析:
将$a,c,e,g...$放一个集合,将$b,d,f,h...$放另一个集合,看它们是否能连线在一起
ac代码:
- #include<bits/stdc++.h>
- #define ll long long
- using namespace std;
- const int maxn=100+10;
- const int maxm=200000*2+10;
- const int mod=1e9+7;
- int num[30];
- char word[maxn];
- int main()
- {
- int T;
- scanf("%d",&T);
- while(T--)
- {
- getchar();
- scanf("%s",word);
- int gkd=0;
- for(int i=0;word[i];i++)
- if((int)word[i]%2!=(int)word[0]%2)gkd=1;
- if(gkd==0)
- {
- printf("%s\n",word);
- continue;
- }
- memset(num,0,sizeof(num));
- for(int i=0; word[i]; i++)
- num[word[i]-'a']++;
- int a,b,fla=0;
- for( int i=0; i<26; i++)
- for(int j=0; j<26; j++)
- if(i%2==0&&j%2==1&&abs(i-j)!=1&&num[j]&&num[i])
- {
- a=i,b=j;
- fla=1;
- }
- if(fla==0)
- {
- printf("No answer\n");
- continue;
- }
- num[a]--;
- num[b]--;
- for(int i=0; i<26; i+=2)
- for(int j=0; j<num[i]; j++)
- printf("%c",(char)(i+'a'));
- printf("%c%c",(char)(a+'a'),(char)(b+'a'));
- for(int i=1; i<26; i+=2)
- for(int j=0; j<num[i]; j++)
- printf("%c",(char)(i+'a'));
- printf("\n");
- }
- return 0;
- }
C. Match Points
题意:
给出n个数,组成最多的数对,满足$|a_i-a_j|\geq d$
分析:
这题一看就是贪心,但是,我的策略是,用最小的去匹配最小能匹配的,wa
例如:
4 2
1 3 4 7
最优解是$(1,4)(3,7)$
正确匹配方式是,用前面一部分匹配后面一部分,对答案二分即可
ac代码:
- #include<bits/stdc++.h>
- #define ll long long
- using namespace std;
- const int maxn=2e5+10;
- const int maxm=200000*2+10;
- const int mod=1e9+7;
- int n,d,num[maxn];
- bool check(int x)
- {
- int a=x,b=n;
- for(;a>=1;a--,b--)
- if(num[b]-num[a]<d)return 0;
- return 1;
- }
- int main()
- {
- scanf("%d %d",&n,&d);
- for(int i=1;i<=n;i++)
- scanf("%d",&num[i]);
- sort(num+1,num+1+n);
- int st=0,en=n/2;
- while(st!=en)
- {
- int md=(st+en)/2;
- if(check(md+1))st=md+1;
- else en=md;
- }
- printf("%d\n",st);
- return 0;
- }
D. 0-1-Tree
题意:
给出一颗节点数为$n$的树,每条边有一个属性0或者1
求出点对$(a,b)$的数量,满足$a$到$b$的最短路线上,经过1之后不经过0
分析:
这样的点对有三种情况
1.$(a,b)$的路径只包含0
2.$(a,b)$的路径只包含1
3.$(a,b)$的路径先全是0,再全是1
对于题目的样例有$ans=5\times 5-5+3\times 3-3+4\times 2=34$
用两个并查集记录0和1的集合和大小。
ac代码:
- #include<bits/stdc++.h>
- #define ll long long
- using namespace std;
- const int maxn=200000+10;
- const int maxm=200000*2+10;
- const int mod=1e9+7;
- int boss[maxn][2];
- ll siz[maxn][2],ans;
- int ma[maxn][2],n;
- int fin0(int x)
- {
- if(boss[x][0]==x)
- return x;
- return boss[x][0]=fin0(boss[x][0]);
- }
- int fin1(int x)
- {
- if(boss[x][1]==x)
- return x;
- return boss[x][1]=fin1(boss[x][1]);
- }
- void uni0(int a,int b)
- {
- boss[fin0(a)][0]=fin0(b);
- }
- void uni1(int a,int b)
- {
- boss[fin1(a)][1]=fin1(b);
- }
- int main()
- {
- scanf("%d",&n);
- for(int i=1; i<=n; i++)
- boss[i][0]=boss[i][1]=i;
- for(int i=1; i<=n-1; i++)
- {
- int a,b,c;
- scanf("%d %d %d",&a,&b,&c);
- ma[a][c]=b;
- ma[b][c]=a;
- if(c==1)
- uni1(a,b);
- else
- uni0(a,b);
- }
- for(int i=1; i<=n; i++)
- {
- siz[fin0(i)][0]++;
- siz[fin1(i)][1]++;
- //cout<<fin1(i)<<endl;
- }
- for(int i=1; i<=n; i++)
- {
- if(boss[i][1]==i)
- {
- //cout<<siz[i][1]<<endl;
- ans+=siz[i][1]*siz[i][1]-siz[i][1];
- }
- if(boss[i][0]==i)
- {
- //cout<<siz[i][0]<<endl;
- ans+=siz[i][0]*siz[i][0]-siz[i][0];
- }
- if(ma[i][0]&&ma[i][1])
- {
- ans+=(siz[fin0(i)][0]-1)*(siz[fin1(i)][1]-1);
- //cout<<i<<" "<<(siz[fin0(i)][0]-1)*(siz[fin1(i)][1]-1)<<endl;
- }
- //cout<<"ans="<<ans<<endl;
- }
- printf("%lld\n",ans);
- return 0;
- }
E. Special Segments of Permutation
题意:
给出$n(3 \le n \le 2 \cdot 10^5)$个数,满足$1 \le p_i \le n$,并且每个数只出现一次
计算区间$(l,r)$的数量,满足$p_l + p_r = \max \limits_{i = l}^{r} p_i$
分析:
用单调栈求出以坐标$i$为最大值的最大区间
然后遍历区间左边或者右边的数,看是否能在另一边找到可以匹配的数
遍历左边或者右边,取决于左右区间的大小,不然一定超时
最初我用递归分治去做,ac了,但是,题目的数据很少,我自己造的数据,会栈溢出
ac代码:
- #include<bits/stdc++.h>
- #define ll long long
- using namespace std;
- const int maxn=2e5+10;
- const int maxm=200000*2+10;
- const int mod=1e9+7;
- struct Node
- {
- int l,r,x;
- }node[maxn];
- int sta[maxn],top=-1,n,pos[maxn];
- int main()
- {
- scanf("%d",&n);
- for(int i=1;i<=n;i++)
- {
- scanf("%d",&node[i].x);
- pos[node[i].x]=i;
- node[i].l=i;
- }
- for(int i=1;i<=n;i++)
- {
- while(top!=-1&&node[i].x>node[sta[top]].x)
- {
- node[sta[top]].r=i-1;
- node[i].l=node[sta[top]].l;
- top--;
- }
- sta[++top]=i;
- }
- while(top!=-1)
- node[sta[top]].r=n,top--;
- int ans=0;
- for(int i=1;i<=n;i++)
- {
- if(i-node[i].l<node[i].r-i)
- {
- for(int j=node[i].l;j<i;j++)
- {
- int x=pos[node[i].x-node[j].x];
- if(x>i&&x<=node[i].r)ans++;
- }
- }
- else
- {
- for(int j=i+1;j<=node[i].r;j++)
- {
- int x=pos[node[i].x-node[j].x];
- if(x>=node[i].l&&x<i)ans++;
- }
- }
- }
- printf("%d\n",ans);
- return 0;
- }
F. Card Bag
题意:
有$n(2 \le n \le 5000)$个卡片在背包里面,每个卡片有一个属性$a_i(1\leq a_i\leq n)$
每次取出一张卡片属性看作$x$,如果上一张有卡片,把上一张卡片属性看作$y$
如果$x=y$,胜利
如果$x<y$,失败
如果$x>y$,游戏继续
求胜利的期望概率
分析:
这题一看就是概率DP
定义$prob[x][y]$为抽出$x$张不重复的卡牌,以$y$作为最后一张的概率
定义$num[x]$为$x$卡牌的数量
那么:
$$prob[x][y]=\frac{num[y]}{n-x+1}\times \sum_{i=1}^{y-1}prob[x-1][i]$$
再枚举所有胜利的情况,抽$x$张牌,以$y$为最后两张的概率
$$ans=ans+prob[x-1][y]\times \frac{num[y]-1}{n-x+1}$$
ac代码:
- #include<bits/stdc++.h>
- #define ll long long
- using namespace std;
- const int maxn=5e3+10;
- const int maxm=200000*2+10;
- const int mod=998244353;
- ll num[maxn];
- ll ans,sum[maxn],prob[maxn][maxn],inv[maxn];
- ll qpow(ll x,ll y)
- {
- ll res=1,k=x;
- while(y)
- {
- if(y&1)res=res*k%mod;
- k=k*k%mod;
- y/=2;
- }
- return res;
- }
- int main()
- {
- int n;
- scanf("%d",&n);
- for(int i=1;i<=n;i++)
- inv[i]=qpow(i,mod-2);
- for(int i=1;i<=n;i++)
- {
- int x;
- scanf("%d",&x);
- num[x]++;
- }
- for(int i=1;i<=n;i++)//prob[x][y]为已经选择了x个数,末尾为y的概率
- {
- prob[1][i]=num[i]*inv[n]%mod;
- for(int len=2;n-len+1>0;len++)
- prob[len][i]=sum[len-1]*num[i]%mod*inv[n-len+1]%mod;
- for(int len=1;len<=n;len++)
- sum[len]=(sum[len]+prob[len][i])%mod;//sum[len]为prob[len][x]的和
- }
- for(int i=1;i<=n;i++)//枚举胜利的所有情况,选择len+1个数,并且以i作为结尾
- if(num[i]>=2)
- for(int len=1;len<n;len++)
- ans=(ans+prob[len][i]*(num[i]-1)%mod*inv[n-len]%mod)%mod;
- cout<<ans<<endl;
- return 0;
- }
总结:
A.没考虑到交点重合的情况,wa了很多发,我应该模拟所有情况的
B.比赛的时候没有思路
C.贪心的策略错了,导致wa了还不知道原因
贪心是最难的算法Orz
E的数据有点少,我可以自己hack我的代码,第一次遇到cf数据有漏洞
栈的深度最大是$5\times 10^{4}$左右,以后要注意
Educational Codeforces Round 64 (Rated for Div. 2) A,B,C,D,E,F的更多相关文章
- Educational Codeforces Round 64 (Rated for Div. 2)题解
Educational Codeforces Round 64 (Rated for Div. 2)题解 题目链接 A. Inscribed Figures 水题,但是坑了很多人.需要注意以下就是正方 ...
- Educational Codeforces Round 64 (Rated for Div. 2) (线段树二分)
题目:http://codeforces.com/contest/1156/problem/E 题意:给你1-n n个数,然后求有多少个区间[l,r] 满足 a[l]+a[r]=max([l, ...
- Educational Codeforces Round 64 (Rated for Div. 2)D(并查集,图)
#include<bits/stdc++.h>using namespace std;int f[2][200007],s[2][200007];//并查集,相邻点int find_(in ...
- Educational Codeforces Round 85 (Rated for Div. 2)
\(Educational\ Codeforces\ Round\ 85\ (Rated\ for\ Div.2)\) \(A. Level Statistics\) 每天都可能会有人玩游戏,同时一部 ...
- Educational Codeforces Round 65 (Rated for Div. 2)题解
Educational Codeforces Round 65 (Rated for Div. 2)题解 题目链接 A. Telephone Number 水题,代码如下: Code #include ...
- Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship
Problem Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...
- Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)
Problem Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...
- Educational Codeforces Round 43 (Rated for Div. 2)
Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...
- Educational Codeforces Round 35 (Rated for Div. 2)
Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...
随机推荐
- Java门面模式(思维导图)
图1 门面模式[点击查看图片] 1,实体对象类 package com.cnblogs.mufasa.demo1; //3个子系统,解决问题的实体 public class StoreA { //示意 ...
- oracle导入时IMP-00010: 不是有效的导出文件, 头部验证失败
头部验证失败是由于版本号不同所致,经试验可以通过如下方法进行修改:用notepad++工具打开dmp文件,可以看到头部信息 --TEXPORT:V11.01.00,即为源数据库的版本号,将其修改为目的 ...
- NOIP2009-2018简要题解
口胡警告 NOIP2009 潜伏者 模拟 Hankson 的趣味题 对四个数\(a_0,a_1,b_0,b_1\)分解质因数,结果序列分别记为\(\{p1^{b1}\},\{p2^{b2}\},\{p ...
- Javascript简单教程汇总
什么是函数 一段定义好的代码,并可以反复使用的代码块 函数的作用 提升代码的可复用性,将一段代码进行预定义,需要使用的时候才触发 代码块 形成了一个相对独立的作用域 语法: function 函数名 ...
- struts-2.5.14.1 中web.xml的基本配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http:// ...
- Nginx如何配置禁止访问某个目录
location ~* \.(txt|doc)${ root /data/www/wwwroot/test; deny all; }
- 文件的空间使用和IO统计
数据库占用的存储空间,从高层次来看,可以查看数据库文件(数据文件,日志文件)占用的存储空间,从较细的粒度上来看,分为数据表,索引,分区占用的存储空间.监控数据库对象占用的硬盘空间,包括已分配,未分配, ...
- scp上传文件到远程服务器
scp -P 22 E:/download/2028792_www.yeves.cn_nginx/cloud.pem root@ip:/usr/local/src
- async/await 处理多个网络请求同步问题
1.async/await是基于Promise的,是进一步的一种优化,await会等待异步执行完成 getProjectTask(id){ this.axios.get('/api/v1/task/' ...
- 【Distributed】限流技巧
一.概述 1.1 高并发服务限流特技 1.2 为什么要互联网项目要限流 1.3 高并发限流解决方案 二.限流算法 2.1 计数器 2.2 滑动窗口计数 2.3 令牌桶算法 使用RateLimiter实 ...