Educational Codeforces Round 80 A-E简要题解

contest链接:https://codeforces.com/contest/1288

A. Deadline

题意:略

思路:根据题意 x + [d/(x+1)] 需要找到一个x使得上式小于等于n,即x + [d/(x+1) ] <=n,不等式两边同时+1得 x+1 + [d/(x+1)] <=n + 1当且仅当(x+1)= d时,式子左边最小,所有只需要判断一下最小值是否<=n+1就可以知道该不等式是否存在x满足题意了,即找到x = √d - 1,判断一下即可。

AC代码:

 1 #include<iostream>
 2 #include<vector>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<set>
 8 #include<cstring>
 9 #include<queue>
10 #include<map>
11 using namespace std;
12 typedef long long ll;
13 int main(){
14     int t;
15     cin>>t;
16     while(t--){
17         ll n,d;
18         cin>>n>>d;
19         if(d<=n){
20             cout<<"YES"<<endl;
21             continue;
22         }
23         ll t = sqrt(d) - 1;
24         ll ans = t + (d/(t+1));
25         if(d%(t+1)!=0) ans++;
26         if(ans<=n){
27             cout<<"YES"<<endl;
28         }
29         else{
30             cout<<"NO"<<endl;
31         }
32     }
33     return 0;
34 }

B. Yet Another Meme Problem

题意:题目定义了一个公式,a×b + a + b = conc(a,b),给出a,b的取值范围,求满足此公式条件的所有pari(a,b)个数

思路:只有当b = 9,99,999....9999999的时候,a为任意值,才满足以上等式,然后判断一下b范围内覆盖的9,99,999...........9999999999即可

AC代码:

 1 #include<iostream>
 2 #include<vector>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<set>
 8 #include<cstring>
 9 #include<queue>
10 #include<map>
11 using namespace std;
12 typedef long long ll;
13 int main(){
14     int t;
15     cin>>t;
16     while(t--){
17         ll a,b;
18         cin>>a>>b;
19         ll tb = b;
20         int cnt = 0;
21         while(b){
22             b/=10;
23             cnt++;
24         }
25         ll s = pow(10,cnt)-1;
26     //    cout<<s<<endl;
27         if(tb != s) cnt--;
28         ll ans = a*cnt;
29         cout<<ans<<endl;
30     }
31     return 0;
32 }

C. Two Arrays

题意:给定一个数n和一个数m,让构建两个数组a和b满足条件,1.数组中所有元素的取值在1~n之间,a和b数组长度是m。2. a数组是单调不递减的,b数组是单调不递增 3. 任意的位置i,有ai<=bi

思路:可以组合数学做,也可以dp,以下为dp做法。首先如果把a、b两个数组合并成 a1,a2,a3,.......am,bm,bm-1,bm-2,bm-3...........b3,b2,b1,会发现整个数列是单调不递减的,那么就可以dp做了,

dp[i][j]表示第i个位置可以放 大于等于 j 的方案数 ,那么转移方程就是 dp[i][j] = dp[i-1][j] + dp[i][j+1]

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxm = 12;
10 const int maxn = 1e3+5;
11 const int mod = 1e9+7;
12 ll dp[maxm*2][maxn];
13 int main(){
14     int n,m;
15     scanf("%d%d",&n,&m);
16     for(int i = 1;i<=n;i++) dp[1][i] = 1;
17     for(int i = 2;i<=2*m;i++){
18         for(int j = n;j>=1;j--){
19             dp[i][j] = (dp[i][j+1] + dp[i-1][j])%mod;
20         }
21     }
22     ll ans = 0;
23     for(int i = 1;i<=n;i++){
24         ans = (ans+dp[2*m][i])%mod;
25     }
26     printf("%d",ans);
27     return 0;
28 }

D. Minimax Problem

题意:给定n个数组,长度为m,从n中数组挑选两个数组,两个数组中的每一位取两者的最大值组成一个新的数组,新数组中的最小值记为c,所有组合中c的最大值

思路:思路:题目中m的范围只有8,数组中元素的范围是1e9,显然m的范围非常特殊,似乎可以把数组用二进制的形式进行状态压缩,这里采用二分答案的方法。二分范围是数组元素最小值到最大值,每次check(mid)一遍,check的时候对于每个数组,用二进制的形式表示出来,数组中小于mid的值用0表示,大于等于mid的用1表示,此时所有的数组都进行了二进制转化,比如一个数组1 2 3 4 5,mid = 3,然后数组就可以状态压缩为0 0 1 1 1  。然后去枚举这些二进制,这样其实最多只会枚举2m × 2m 次,如果枚举的两组二进制相或为11111111,那么说明找到了一组解,返回继续二分,如此过程时间复杂度只有O(n×m + 2m×2m),m的范围只有8。具体看代码

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxn = 3e5+5;
10 int n,m;
11 int cnt[maxn];
12 int a[maxn][10];
13 int num[270];
14 int ans1,ans2;
15 bool check(int cur){
16     memset(num,0,sizeof(num));//初始化num数组
17     for(int i = 1;i<=n;i++){
18         int x = 0;
19         for(int j = m - 1;j>=0;j--){
20             if(a[i][j]>=cur) x+=(1<<j);///统计满足a[i][j]>=cur的数组的每一位
21         }
22         num[x] = i;//每个数组都转化为二进制
23     }
24     for(int i = 0;i<(1<<m);i++){
25         for(int j = 0;j<(1<<m);j++){
26             if(num[i]!=0 && num[j]!=0 && (j|i) == (1<<m)-1){//枚举二进制形式的所有数
27                 ans1 = num[i];
28                 ans2 = num[j];
29                 return true;
30             }
31         }
32     }
33     return false;
34 }
35 int main(){
36     int r = -1,l = 1e9+10;
37     scanf("%d%d",&n,&m);
38     for(int i = 1;i<=n;i++){
39         for(int j = 0;j<m;j++){
40             scanf("%d",&a[i][j]);
41             r = max(r,a[i][j]);
42             l = min(l,a[i][j]);
43         }
44     }
45     int mid;
46     while(l<r){//二分答案
47         mid = (l+r+1)/2;
48         if(check(mid)) l = mid ;
49         else r = mid - 1;
50     }
51     check(l);
52     printf("%d %d",ans1,ans2);
53     return 0;
54 }

E. Messenger Simulator

题意:序列p的长度为n,初始序列为1 2 3 4 ...n,然后有m次操作,每次指定序列中一个数移动到第一位,然后剩下的所有序列往后移动一位,求每个数在出现过的所有历史序列中所在位置索引的最大值和最小值。

思路:用一个树状数组维护序列的位置,在序列的前面空出m个位置,目的是留给m次操作移动数字到前m个位置。初始时,在输入数据的时候,用pos数组记录所有数字的位置为 i+m,然后树状数组的 i+m处更新+1代表第i+m个位置放了一个数,每次移动操作时,在该位置做-1的更新操作表示此处清零,该位置已经没有放置数字,然后可以用树状数组查询该位置前面部分的区间和,就表示前面有多少个数,自然而然就可以更新这个数出现位置的最大值了,而最小值更新则为:如果进行了移动操作,那么该数字位置的最小值就是1了,因为把该数字放在了序列最前面,最后再遍历一遍所有数字,查询更新一些没有进行移动操作的数出现位置的最大值。具体看代码

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxn = 3e5+5;
10 int t[maxn*2];
11 int ansMin[maxn+1],ansMax[maxn+1];
12 int n,m;
13 inline int lowbit(int x){
14     return x&(-x);
15 }
16 void add(int x,int k){
17     while(x<=n+m){
18         t[x] = t[x] + k;
19         x +=lowbit(x);
20     }
21 }
22 int get(int x){
23     int ans = 0;
24     while(x>=1){
25         ans+=t[x];
26         x-=lowbit(x);
27     }
28     return ans;
29 }
30 int main(){
31     scanf("%d%d",&n,&m);
32     int pos[n+m+1];
33     for(int i = 1;i<=n;i++){
34         pos[i] = i + m;//初始化元素的位置,pos[i]为元素i的位置
35         ansMin[i] = i,ansMax[i] = i;
36         add(i + m,1);//树状数组该位置更新+1
37     }
38     for(int i = 0;i<m;i++){
39         int temp;
40         scanf("%d",&temp);
41         ansMin[temp] = 1;
42         add(pos[temp],-1);//该位置-1,
43         add(m-i,1);//移动到最前面,树状数组+1
44         ansMax[temp] = max(ansMax[temp],get(pos[temp]));//查询前面有多少个元素,做max的更新
45         pos[temp] = m - i;//更新位置
46     }
47     for(int i = 1;i<=n;i++){
48         ansMax[i] = max(ansMax[i],get(pos[i]));//最后check没有进行移动操作的元素
49     }
50     for(int i = 1;i<=n;i++){
51         printf("%d %d\n",ansMin[i],ansMax[i]);
52     }
53     return 0;
54 }
55
56
57  

b

)

原文地址:https://www.cnblogs.com/AaronChang/p/12210863.html

时间: 2024-10-09 00:39:34

Educational Codeforces Round 80 A-E简要题解的相关文章

Educational Codeforces Round 80 (Rated for Div. 2)

\[Educational\ Codeforces\ Round\ 80\ (Rated\ for\ Div.\ 2)\] A.Deadline 打勾函数找最小值,在\(\sqrt{d}\)邻域里找\(x\)最小化\(x+\lceil\frac{d}{x+1}\rceil\)即可 //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<bits/stdc++.h> using namespace

题解 Educational Codeforces Round 80 [Rated for Div. 2](CF1288)

前言:11点的时候某天下第一可爱的萌神问我怎么不打CF,跑去开题,11:30终于开了C和D,秒了一下,考后萌神轻松上分并告诉我E的tag于是我赛后补题. A:n/x上取整是(n-1)/x+1,式子变形成x+1+(n-1)/(x+1)<=d.根据a+b>=2√ab随便化简一下.(20s秒了??) 1 #include<stdio.h> 2 #include<math.h> 3 using namespace std; 4 int T,n,d,x,y; 5 int main

Educational Codeforces Round 80 (Rated for Div. 2)部分题解

A. Deadline 题目链接 题目大意 给你\(n,d\)两个数,问是否存在\(x\)使得\(x+\frac{d}{x+1}\leq n\),其中\(\frac{d}{x+1}\)向上取整. 解题思路 方案一:利用均值不等式公式推导 \(x+\frac{d}{x+1}=x+1+\frac{d}{x+1}-1\geq2\sqrt{d}-1\) 所以 \(\min(x+\frac{x}{d+1})=2\sqrt{d}-1\) 因此去判断\(2\sqrt{d}-1\leq n\)是否成,即\(4\

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

Deadline Yet Another Meme Problem Two Arrays Minimax Problem Messenger Simulator Deadline \[ Time Limit: 2 s\quad Memory Limit: 256 MB \] 这是个对勾函数,所以最小的话是在 \(sqrt\) 位置,所以只要找这附近的数字就可以了. view /************************************************************

Codeforces Round #483 (Div. 1) 简要题解

来自FallDream的博客,未经允许,请勿转载,谢谢. 为了证明一下我又来更新了,写一篇简要的题解吧. 这场比赛好像有点神奇,E题莫名是道原题,导致有很多选手直接过掉了(Claris 表演24s过题).然而D题比E题要难一些,分还少. A. Finite or not? 先把\(\frac{p}{q}\)约成最简分数,然后就是要判断是否\(q\)的所有质因数都是\(b\)的质因数. 每次取\(g=gcd(b,q)\),并尽可能的让\(q\)除\(g\),最后判断\(q\)是否是1即可. 还有一

Codeforces Round #498 (Div. 3) 简要题解

[比赛链接] https://codeforces.com/contest/1006 [题解] Problem A. Adjacent Replacements        [算法] 将序列中的所有偶数替换为奇数即可 时间复杂度 : O(N) [代码] #include<bits/stdc++.h> using namespace std; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y);

Educational Codeforces Round 80 (Rated for Div. 2)(C - Two Arrays )

C - Two Arrays 题目链接:https://codeforces.com/contest/1288/problem/C 题目: 题意:给你n,m,利用1~n之间的数(可重复)来组成长度为m的数组a,b,要求数组a非递减,数组b非递增,且a数组的数<=b数组中的数,求出a,b数组对数 思路:用动态规划,dp[i][j]是第i个位置放数字j的方案数,根据题意可以将b数组反置然后接在a后面,则该数组长度为2m,为一个非递减序列,则就是求1~n这些数字可重复组成多少种长度为2m的非递减序列,

Educational Codeforces Round 80 (Rated for Div. 2)参加感悟

这次比赛有14000+的人报名,结果我得了266名,创了新纪录. 进过这次比赛,我有回答了1800+. 寒假到了,又可以每次比赛都打了.平时进步很慢,我希望能在寒假有更大的进步. 作为寒假第一场比赛,发挥让我还是很满意的. 开始讲题: A: http://codeforces.com/contest/1288/problem/A 这题太水了,直接是sqrt(d)-1和sqrt(d),如果它们不行,那么其他的也肯定不行. 直接上代码: 1 #include<bits/stdc++.h> 2 #d

Educational Codeforces Round 80 (Rated for Div. 2)(A-E)

C D E 这三道题感觉挺好 决定程序是否能通过优化在要求的时间内完成,程序运行时间为t,你可以选择花X天来优化,优化后程序的运行时间为t/(x+1)取上整,花费的时间为程序运行时间加上优化时间 如果程序运行时间小于等于要求时间,那就不需要优化,否则必须优化,假设优化X天,那么总时间就是X+t/(X+1) ,我们的目标事求他的最小值,根据均值不等式 另外均值不等式中等于号成立的条件是x1=x2=....xn code #include<cstdio> #include<algorithm