题解 Codeforces Round #615 (Div. 3) (CF1294)

A:判断一下和是不是3的倍数,由于只加不减,所以还要判断有没有大于和的1/3。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #define it register int
 5 #define ct const int
 6 #define il inline
 7 using namespace std;
 8 int T,a,b,c,n,x;
 9 namespace io{
10     il char nc(){
11         static char buf[100000],*p1=buf,*p2=buf;
12         return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
13     }
14     template <class I>
15     il void fr(I &num){
16         num=0;register char c=nc();it p=1;
17         while(c<‘0‘||c>‘9‘) c==‘-‘?p=-1,c=nc():c=nc();
18         while(c>=‘0‘&&c<=‘9‘) num=num*10+c-‘0‘,c=nc();
19         num*=p;
20     }
21 };
22 using io :: fr;
23 int main(){
24     fr(T);
25     while(T--){
26         fr(a),fr(b),fr(c),fr(n);
27         if((a+b+c+n)%3){puts("NO");continue;}
28         x=(a+b+c+n)/3;
29         if(a>x||b>x||c>x){puts("NO");continue;}
30         puts("YES");
31     }
32     return 0;
33 }

B:发现只能向上和向右。所以我们必须保证序列在两维上非降。那么按照x,y升序排序,然后判断一下对于这个点是否存在x比它的x小且y比它的y大,有就是无解。由于字典序要小,所以肯定先右“R”再上“U”。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #define it register int
 5 #define ct const int
 6 #define il inline
 7 using namespace std;
 8 const int N=100005;
 9 int T,n,lastx,lasty;
10 bool flag;
11 struct ky{
12     int x,y;
13 }a[N];
14 bool cmp(ky p,ky q){
15     return p.x^q.x?p.x<q.x:p.y<q.y;
16 }
17 int main(){
18     scanf("%d",&T);it i;
19     while(T--){
20         scanf("%d",&n);
21         for(i=1;i<=n;++i) scanf("%d%d",&a[i].x,&a[i].y);
22         std::sort(a+1,a+1+n,cmp);
23         flag=0;
24         for(i=1;i<=n;++i)
25             if(a[i].x!=a[i-1].x&&a[i].y<a[i-1].y) flag=1,i=n+1;
26         if(flag){puts("NO");continue;}
27         lastx=0,lasty=0,puts("YES");
28         for(i=1;i<=n;++i){
29             for(it j=lastx;j<a[i].x;++j) putchar(‘R‘);
30             for(it j=lasty;j<a[i].y;++j) putchar(‘U‘);
31             lastx=a[i].x,lasty=a[i].y;
32         }
33         putchar(‘\n‘);
34     }
35     return 0;
36 }

C:先在√n时间内算出n的因子个数,判断是否有解,注意除去n的1与本身这两个因子。在有解的情况下找出两个小于√n的一个大于√n的(若有解肯定存在)即可。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #define it register int
 5 #define ct const int
 6 #define il inline
 7 using namespace std;
 8 int T,a,b,c,n,x,ans1,ans2,ans3;
 9 namespace io{
10     il char nc(){
11         static char buf[100000],*p1=buf,*p2=buf;
12         return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
13     }
14     template <class I>
15     il void fr(I &num){
16         num=0;register char c=nc();it p=1;
17         while(c<‘0‘||c>‘9‘) c==‘-‘?p=-1,c=nc():c=nc();
18         while(c>=‘0‘&&c<=‘9‘) num=num*10+c-‘0‘,c=nc();
19         num*=p;
20     }
21 };
22 using io :: fr;
23 int main(){
24     fr(T);it i;register long long now=1;
25     while(T--){
26         fr(n);
27         it x=n,cnt=0;now=1;
28         for(i=2;i*i<=x;++i)
29             if(!(x%i)){
30                 cnt=0;
31                 while(!(x%i))
32                     x/=i,++cnt;
33                 now*=(cnt+1ll);
34             }
35         if(x>1) now<<=1;
36         now-=2;
37         if(now<3){puts("NO");continue;}
38         x=n,cnt=0,ans1=ans2=0;
39         for(i=2;cnt<2&&i*i<=x;++i)
40             if(!(x%i))
41                 ++cnt,x/=i,cnt==1?ans1=i:(cnt==2?ans2=i:ans3=i);
42         if(cnt==2&&x>ans2&&ans2)
43             puts("YES"),printf("%d %d %d\n",ans1,ans2,x);
44         else puts("NO");
45     }
46     return 0;
47 }

D:构建mod x的剩余系,每次找到这个剩余系里面最大的加上x即可。注意到最多进行n次操作,所以>=n的其实没啥意义。然后怎么找第一个未出现过的元素:很显然按照我的添加方法肯定每个数只出现一次。所以维护一个set,只要每次把出现过的删掉,输出s.begin()(第一个元素也就是最小的没被删掉的,即还没出现的)即可。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<bitset>
 4 #include<set>
 5 #include<algorithm>
 6 #define it register int
 7 #define ct const int
 8 #define il inline
 9 using namespace std;
10 const int N=1000005;
11 int T,a,b,c,n,x,f[N],maxn;
12 set<int> s;
13 namespace io{
14     il char nc(){
15         static char buf[100000],*p1=buf,*p2=buf;
16         return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
17     }
18     template <class I>
19     il void fr(I &num){
20         num=0;register char c=nc();it p=1;
21         while(c<‘0‘||c>‘9‘) c==‘-‘?p=-1,c=nc():c=nc();
22         while(c>=‘0‘&&c<=‘9‘) num=num*10+c-‘0‘,c=nc();
23         num*=p;
24     }
25 };
26 using io :: fr;
27 bitset<N> vs;
28 int main(){
29     fr(n),fr(x);it i,nowmax=-1,y;maxn=-1;
30     for(i=0;i<x;++i) f[i]=-1;
31     for(i=0;i<=n;++i) s.insert(i);
32     for(i=1;i<=n;++i){
33         fr(y),y%=x;
34         f[y]==-1?f[y]=y:f[y]+=x;
35         if(f[y]<=400000) s.erase(f[y]);
36         printf("%d\n",*s.begin());
37     }
38     return 0;
39 }

E:这个题的意思就相当于要我们每次可以重置和交换整行,思路肯定是枚举,用桶记一下最小值。然后还是和剩余系的思路一样。

 1 #include<stdio.h>
 2 #include<vector>
 3 #include<algorithm>
 4 #define it register int
 5 #define ct const int
 6 #define il inline
 7 using namespace std;
 8 const int N=200005;
 9 vector<int> a[N];
10 int s[N],o,n,m;
11 il int Min(ct p,ct q){return p<q?p:q;}
12 namespace io{
13     il char nc(){
14         static char buf[100000],*p1=buf,*p2=buf;
15         return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
16     }
17     template <class I>
18     il void fr(I &num){
19         num=0;register char c=nc();it p=1;
20         while(c<‘0‘||c>‘9‘) c==‘-‘?p=-1,c=nc():c=nc();
21         while(c>=‘0‘&&c<=‘9‘) num=num*10+c-‘0‘,c=nc();
22         num*=p;
23     }
24 }
25 using io :: fr;
26 void solve(ct x){
27     it i,ans=n;
28     for(i=0;i<=n;++i) s[i]=0;
29     for(i=1;i<=n;++i)
30         if(a[x][i]%m==x%m&&(a[x][i]+m-1)/m<=n) ++s[(i-(a[x][i]+m-1)/m+n)%n];
31     for(i=0;i<=n;++i) ans=Min(ans,i+n-s[i]);
32     o+=ans;
33 }
34 int main(){
35     fr(n),fr(m);it i,j,x;
36     for(i=1;i<=m;++i) a[i].push_back(0);
37     for(i=1;i<=n;++i)
38         for(j=1;j<=m;++j)
39             fr(x),a[j].push_back(x);
40     for(i=1;i<=m;++i) solve(i);
41     printf("%d",o);
42     return 0;
43 }

F:明明还剩00:01:06的时候交F可是没交上去呜呜呜。思路是先以1为根找出深度最大的mx1,再以mx1为根找出深度最大的mx2,然后沿着这条路把路上的点标记一下,再找到深度最大的mx3。每次找的时候ans++记录路径长度。由于x个点会有x-1条路,所以最后答案为ans-1.

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<bitset>
 4 #include<algorithm>
 5 #define it register int
 6 #define ct const int
 7 #define il inline
 8 using namespace std;
 9 const int N=1000005;
10 int h[N],nxt[N],adj[N],fa[N],ans,mx1,mx2,mx3,u,v,n,m,t,id,d[N];
11 bitset<N> vs;
12 namespace io{
13     il char nc(){
14         static char buf[100000],*p1=buf,*p2=buf;
15         return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
16     }
17     template <class I>
18     il void fr(I &num){
19         num=0;register char c=nc();it p=1;
20         while(c<‘0‘||c>‘9‘) c==‘-‘?p=-1,c=nc():c=nc();
21         while(c>=‘0‘&&c<=‘9‘) num=num*10+c-‘0‘,c=nc();
22         num*=p;
23     }
24 }
25 using io :: fr;
26 il void dfs(ct x){
27     d[x]=(vs[x]?1:d[fa[x]]+1);
28     for(it i=h[x],j;i;i=nxt[i])
29         if((j=adj[i])!=fa[x])
30             fa[j]=x,dfs(j);
31 }
32 il void add(){
33     nxt[++t]=h[u],h[u]=t,adj[t]=v,nxt[++t]=h[v],h[v]=t,adj[t]=u;
34 }
35 int main(){
36     fr(n);it i;
37     for(i=1;i<n;++i) fr(u),fr(v),add();
38     dfs(1);
39     for(i=1;i<=n;++i){fa[i]=0;if(d[i]>d[mx1]) mx1=i;}
40     dfs(mx1);
41     for(i=1;i<=n;++i) if(d[i]>d[mx2]&&i!=mx1)mx2=i;
42     for(i=mx2;i;i=fa[i]) vs[i]=1,++ans;
43     dfs(mx1);
44     for(i=1;i<=n;++i) if(d[i]>d[mx3]&&i!=mx1&&i!=mx2)mx3=i;
45     for(i=mx3;!vs[i];i=fa[i]) vs[i]=1,++ans;
46     printf("%d\n%d %d %d",ans-1,mx1,mx2,mx3);
47     return 0;
48 }

由于博主已经意识模糊,所以可能会有一些纰漏,请大家指出,谢谢。

这次唯一的收获大概就是一题没挂,于是用大号刷高了小号的rating(雾

大号打Div3不能增加Rating了QAQ,但为了好看还是用小号去刷大号正确率,结果每次都是一遍A,然后提高了小号的Rating……

原文地址:https://www.cnblogs.com/Kylin-xy/p/12230069.html

时间: 2024-10-11 07:41:11

题解 Codeforces Round #615 (Div. 3) (CF1294)的相关文章

Codeforces Round #615 (Div. 3) A-F简要题解

contest链接:https://codeforces.com/contest/1294 A. 给出a.b.c三个数,从n中分配给a.b.c,问能否使得a = b = c.计算a,b,c三个数的差值之和,n对其取余,判断是否为0即可. AC代码: 1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring>

Codeforces Round #615 (Div. 3) 题解

A - Collecting Coins 题意: 给你四个数a,b,c,d,n.问你是否能将n拆成三个数A,B,C,使得A+a=B+b=C+c. 思路: 先计算三个数的差值的绝对值abs,如果abs大于n则肯定不行,如果小于n,还需判断(n-abs)%3是否为0,不为0则不行. #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<vector

Codeforces Round #615(div.3) A 题解

题意: 分别有a,b,c个硬币在对应的三个人手中,我有n个硬币,问如何将这n个硬币分给这三个人使得最后三个人的硬币数相同. 思路: 先求出每个人与最多的人的硬币个数的差距,然后拿n个硬币去填补这个空缺,分过剩下来没有分的如果可以%3==0,则说明可以相同.如果不为0则说明无法分配. 水题一道: #include<iostream> #include<algorithm> using namespace std; int main() { int t; cin>>t; w

题解Codeforces Round #595 (Div. 3)(CF1249)

开题1小时(雾)严重影响我的提交以及做题心情..我刚开题就发现有人阿克了.. 实际上这场div3真心简单良心很休闲. A:送分题,先排序,每次枚举一下这个数可以加到哪个集合里,加进去就行. 1 #include<stdio.h> 2 #include<algorithm> 3 #define it register int 4 #define il inline 5 using namespace std; 6 const int N=1000005; 7 int a[N],o[N

Codeforces Round #615 (Div. 3). D - MEX maximizing

题面:https://codeforces.com/contest/1294/problem/D 题目大意: 每次都会往你的数列里加一个值,你可以任意加减这个值若干次(但是只能加x或者减x) 然后问最小的不属于这个数列的非负整数是什么 你需要进行的操作是,让这个最小的不属于这个数列的非负整数最大 每次加一个值并且询问一遍 解题思路: 易得到,每一次输出的答案在进行完题目的贪心后会呈现上升趋势,且值最大只可能为序列内元素的个数 所以我们可以让每次加入的值在进行完若干次操作后尽量成为靠前的序列中还没

Codeforces Round #615 (Div. 3)

暂时没有F题的题解.太菜了. A - Collecting Coins 题意:有三个人,分别有a,b,c枚硬币,你有n枚硬币,要求把n枚硬币全部给这三个人并且使得他们的硬币数变为相等.问是否可行. 题解:先验证硬币总数a+b+c+n是否能被3整除,然后验证要补的硬币的数量少于n. void test_case() { int a[5], n; scanf("%d%d%d%d", &a[1], &a[2], &a[3], &n); sort(a + 1,

Codeforces Round #615 (Div. 3). B - Collecting Packages

题面:https://codeforces.com/contest/1294/problem/B 题目大意: 机器人从(0,0)开始,他只能往上'U'或者往右'R'走 坐标系中有着很多包裹,分别在一些点上 机器人需要走过去把这些包裹全部收集起来 问能不能做到 如果能,再输出移动方式,相同移动方式输出字典序最小的方案 解题思路: pair或者结构体排序,x与y的优先级任意,因为下一个包裹必定在当前机器人位置右方/上方/右上方 否则直接输出NO,表示不可能存在这种移动方式 在输出移动方式时,注意能先

Codeforces Round #615 (Div. 3) F. Three Paths on a Tree

F. Three Paths on a Tree 原题链接:https://codeforces.com/contest/1294/problem/F 题目大意: 给定一棵树,选出三点,使三点连成的j简单路径最大.简而言之,三个点连成的边的集合大小. 解题思路: 假设任取一点为三点连线的公共点,最长路径就是这个点到其他三个点的三条最长边之和,可知这个点一定在直径上(画图分析假设不在时的最长路径可反证).所以先求出树的直径,在使用$ans =(a b+a c+b c) / 2$遍历可以得到第三个点

Codeforces Round #615 (Div. 3) E. Obtain a Permutation

E. Obtain a Permutation 原题链接:https://codeforces.com/contest/1294/problem/E 题目大意: 给一个无序矩阵,可以进行两个操作: 1.改变任何元素的大小: 2.将任何一列中的元素向上提一位,也就是$a_{1, j}:=a_{2, j}, a_{2, j}:=a_{3, j}, \dots, a_{n, j}:=a_{1, j}$ 使得最后的矩阵变为有序的序列,即$\left.a_{1,1}=1, a_{1,2}=2, \ldot