Codeforces Round #654 (Div. 2)A-E2题解

A. Magical Sticks

传送门
题意:给你n个数字,其中的数字可以随机组合,问可以组合形成最多同时几个数相等
题解:找规律即可,如果n为偶数,则有n/2个,反正(n+1)/2个

#include<iostream>
#include<cstring>
#include<algorithm> 
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--){
		int n;
		cin>>n;
		cout<<(n+1)/2<<endl;
	} 
	return 0;
}

B. Magical Calendar

传送门
题意:有连续的n天,她可以选择任何满足1≤k≤r的整数k,并将k天设置为一周中的天数。如果日期到达一周的最后一天,则第二天的单元格是下一行(下方)中最左边的单元格。你可以选择从一周的任意一天开始,问有多少种不同的单元格形状。
题解:画图找规律可以发现,当k<n时的不同形状的单元格个数与选择的k值相同,即和为等差数列r(1+r)/2*,k>=n的部分形状平移之后形状都是一样的,所以只需要加1;
第一种情况r<n: 输出r(1+r)/2;
第二种情况r>=n:输出(n-1)
(1+n-1)/2+1;
**

#include<iostream>
#include<cstring>
#include<algorithm> 
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--){
		int n,r;
		cin>>n>>r;
		if(n>r) cout<<r*1ll*(1+r)/2<<endl;
     else cout<<1ll*(n-1)*(1+n-1)/2+1<<endl;
	} 
	return 0;
}

C. A Cookie for You

传送门
题意:有两种曲奇,数量分别为a,b,有两类人个数为n(每一个人都会选择一个数目多的那种曲奇),m(每个人都会选择一个数目少的那种曲奇),如果a=b时可以随便选一个,问是否每个人都能够拿到任意一种类型的曲奇;
题解:如果(a+b)<(n+m)时肯定有人选不到那么如果(a+b)>=(n+m) 的情况下我们只需要考虑第二类人m(每个人都会选择一个数目少的那种曲奇)能否都能选到,如果a,b中的最小值大于等于m,则每个人都能选到,因为第一类人n(每一个人都会选择一个数目多的那种曲奇)能够在a=b的时候随便选一个,以此下去可以选到所有的数,所以不用考虑

#include<iostream>
#include<algorithm> 
using namespace std;
long long int a,b,n,m,c;
int main()
{
	int t;
	cin>>t;
	while(t--){
	cin>>a>>b>>n>>m;
	if((a+b)<(n+m)) cout<<"No"<<endl;
	//第一种情况
	else{
		 a=min(a,b);
	    if(a>=m) cout<<"Yes\n"; 
	    //找到最小值满足m个人需求即可
		else cout<<"No\n";
		  
	}
	}
	return 0;
}

Problem D - Grid-00100

传送门
题解:当k能被n整除时,是可以使得每一行每一列个数相同的,如果有余数的话,把余数错开放在每行后面一个1,可以使得满足1+1=2 的情况的。
就这样构造:
在这里插入图片描述
上代码吧

#include<bits/stdc++.h>
using namespace std;
const int maxn=305;
int n,k,t;
int a[maxn][maxn];
int main () {
	scanf("%d",&t);
	while (t--) {
		scanf("%d%d",&n,&k);
		if (k%n==0) printf("0\n");
		else printf("2\n");
		int tt=0;
		memset(a,0,sizeof(a));
		for (int i=1;i<=k/n;i++) {
			for (int j=0;j<n;j++) a[j][(j+tt)%n]=1;
			tt++;
			//先每行错开放k/n个,保f(A)=0;
		}
		if (k%n) for (int i=0;i<k%n;i++) a[i][(i+tt)%n]=1;
		//再将剩余的1错开放在前k%n行中。
		for (int i=0;i<n;i++) {
			for (int j=0;j<n;j++) printf("%d",a[i][j]);
			printf("\n");
		}
	} 
	return 0}

1371E1 - Asterism (Easy Version)

传送门
题解:让我们来定义m=max(a1,a2,…,an).

玉祖至少应该m−n+1糖果最初是为了赢得所有决斗,然后f(x)=0为x<m−n+1。这可以被p.

如果五十铃有相等的或更多的.m糖果一开始,任何排列都是有效的,然后f(x)=n!为x≥m。这可以被p也是。(因为p≤n)

然后,在这个子任务中,您应该找到每个f(x)可被p为m−n+1≤x<m在……里面O(n).

您可以找到f(x)通过以下模拟:

首先,让v={他们的敌人数量严格地少于x糖果),ans=1.
然后执行以下步骤i=x,x+1,…,x+(n−1).
v=v+{他们有多少敌人i糖果)
ans=ans∗v
v=v−1
现在,p是个质数。然后,“是否f(x)可被p“是”是否p乘成ans如v至少有一次。“

这可以在O(n)每个人的时间x.

总复杂性:O(n2)

#include<stdio.h>
 
int max(int a,int b){if(a>b){return a;}return b;}
 
int main(){
  int n,p;
  int st,fi;
  int a[131072],bk[262144]={0},bas=0,i,j;
  int res[131072],rc=0;
  scanf("%d%d",&n,&p);
  for(i=0;i<n;i++){
    scanf("%d",&a[i]);
    bas=max(a[i],bas);
  }
  for(i=0;i<n;i++){bk[max(0,a[i]-bas+n)]++;}
  for(i=1;i<262144;i++){bk[i]+=bk[i-1];}
  for(i=0;i<=n;i++){
    for(j=0;j<n;j++){
      if((bk[i+j]-j)<=0){break;}
      if((bk[i+j]-j)%p==0){break;}
      if(j==n-1){res[rc]=i+(bas-n);rc++;}
    }
  }
  printf("%d\n",rc);
  for(i=0;i<rc;i++){
    if(i){printf(" ");}
    printf("%d",res[i]);
  }printf("\n");
}

1371E2 - Asterism (Hard Version)

传送门
题解:
在这里插入图片描述

#include<stdio.h>
 
int max(int a,int b){if(a>b){return a;}return b;}
 
int main(){
  int n,p;
  int st,fi;
  int a[131072],bk[262144]={0},bas=0,i;
  scanf("%d%d",&n,&p);
  for(i=0;i<n;i++){
    scanf("%d",&a[i]);
    bas=max(a[i],bas);
  }
  for(i=0;i<n;i++){bk[max(0,a[i]-bas+n)]++;}
  for(i=1;i<262144;i++){bk[i]+=bk[i-1];}
 
  st=1;
  for(i=1;i<=n;i++){
    while(bk[st+(i-1)]<i){st++;}
  }
  st+=(bas-n);
 
  fi=n;
  for(i=1;i<=n;i++){
    while(fi>0){
      if(bk[fi+(i-1)]-(i-1)<p){break;}
      fi--;
    }
  }
  fi+=(bas-n);
 
  if(st>fi){
    printf("0\n\n");
    return 0;
  }
  printf("%d\n",fi-st+1);
  for(i=st;i<=fi;i++){
    if(i!=st){printf(" ");}
    printf("%d",i);
  }printf("\n");
  return 0;
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Think-killer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值