Codeforces Round #638 (Div. 2)

Codeforces Round #638 (Div. 2)

CF1348A
A - Phoenix and Balance
给一个数n即你有2、4、8、16…2^n这些数,把他分成两堆保证和的差值最
很容易知道前n-1项和小于第n项,2^n-2 和2的n次方,所以把最后一项和前面几项相加使得和靠近总和的一半就行

#include <iostream>
#include <algorithm>
using namespace std;
int main(){	
	int t;	
	scanf("%d",&t);	
	while(t--){		
		int n;		
		scanf("%d",&n);		
		long long sum=0;		
		long long ans=1<<n;		
		sum=ans+(1<<(n/2))-2;		
		printf("%lld\n",sum-((1<<(n+1))-2-sum));	
	}	
	return 0;
}

CF1348B

B - Phoenix and Beauty
插入1-n中的数使得任何连续的k个数和相等
先检查n个数中有多少个不同的数,如果超过k那么直接输出-1不可能实现,自己可以想想看,如果小于k那就从1-n中选几个数使得可选数的个数等于k,然后顺序可以随便了打印n次可选数序列总个数当然就是n*k了,等于k的话就免去了从1-n中选可选数的步骤,代码比较冗余,当时没想着怎么缩短

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
int a[105];
int vis[105];
int main() {
	int t;
 	scanf("%d",&t);
 	while(t--) {
  		int n,k;
  		scanf("%d%d",&n,&k);
 	 	memset(vis,0,sizeof(vis));
  		vector<int>v;
  		for (int i=0; i<n; i++)  scanf("%d",a+i);
  		if (n==k) {
   			printf("%d\n",n);
   			printf("%d",a[0]);
   			for (int i=1; i<n; i++)  printf(" %d",a[i]);
   			printf("\n");
  		} else {
   			int num=0;
   			for (int i=0; i<n; i++) {
    				if (vis[a[i]]==0) {
     					v.push_back(a[i]);
     					num++;
    				}
    				vis[a[i]]++;
   			}
   			if (num>k)  printf("-1\n");
  			else {
    				printf("%d\n",k*n);
    				if (num<k) {
     					for (int i=1; i<=n; i++) {
      						if (vis[i]==0&&num<k)  v.push_back(i),num++;
     					}
    				}
    				int flag=0;
    				int nflag=0;
    				while(flag<n) {
     					flag++;
     					for (int j=0; j<v.size(); j++) {
      						if (nflag) printf(" ");
      						nflag=1;
      						printf("%d",v[j]);
    					}
  				}
  				printf("\n");
   			}
  		}
 	}
 return 0;
}

CF1348C
C - Phoenix and Distribution
看出现的最小的字母有多少个,如果小于k就可以顺延按照这段序列排序的第k个字符,因为剩下的字符都可以放在最小的那个字符后面,如果等于k就看这段序列中一共出现过几个不同的字符来分别处理

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int num[30];
int main() {
 	int t;
 	scanf("%d",&t);
 	while(t--) {
  		int n,k;
  		scanf("%d%d",&n,&k);
  		string s;
  		cin>>s;
  		int i=0;
  		memset(num,0,sizeof(num));
 		 while(s[i]) {
   			num[s[i]-'a']++;
   			i++;
  		}
  		int pos;
  		for (int j=0; j<26; j++) {
   			if (num[j]!=0) {
    				pos=j;
    				break;
   			}
  		}
  		if (num[pos]<k) {
   			int ans=num[pos];
   			for (int j=pos+1; j<26; j++) {
    				if (num[j]!=0){
     					ans+=num[j];
     					if (ans>=k){
      						printf("%c\n",j+'a');
     				 		break;
     					}
    				}
   			}
  		} else {
  			int ans=0;
   			for (int j=0; j<26; j++) if (num[j]!=0) ans++;
   			if (ans==1) {
    				int num1=num[pos];
    				if (num1%k) num1=num1/k+1;
    				else num1=num1/k;
   			 	while(num1--) {
     					printf("%c",pos+'a');
   		 		}
    				printf("\n");
   			} else if (ans==2) {
    				if (num[pos]==k) {
     					printf("%c",pos+'a');
     					for (int j=pos+1; j<26; j++) {
      						if (num[j]!=0) {
      	 						pos=j;
       							break;
      						}
     					}	
	     				int num1=num[pos];
     					if (num1%k) num1=num1/k+1;
     					else num1=num1/k;
    	 				while(num1--) {
      						printf("%c",pos+'a');
     					}
     					printf("\n");
    				} else {
     					printf("%c",pos+'a');
     					num[pos]-=k;
     					for(int j=pos; j<26; j++) {
      						while(num[j]--) {
       							printf("%c",j+'a');
      						}
     					}
     					printf("\n");
    				}
   			} else {
    				printf("%c",pos+'a');
    				num[pos]-=k;
    				for(int j=pos; j<26; j++) {
     					while(num[j]--) {
      						printf("%c",j+'a');
     					}
    				}
    				printf("\n");
   			}
  		}
 	}
 	return 0;
}

CF1348D
D - Phoenix and Science
每天白天你可以选择已有的x个细胞中y个细胞分裂y>=0&&y<=x每天晚上每个细胞会增加1的重量,求最快到达n的重量的方法
总之就是贪心的策略,只不过要考虑最后两天的处理

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
 int t;
 scanf("%d",&t);
 while(t--){
  long long n;
  scanf("%lld",&n);
  if (n==2)  printf("1\n0\n");
  else{
   vector<long long>v;
   int nflag=0;
   long long num=2;
   long long num1=1;
   int ans=0;
   long long sum=1;
   while(sum<n){
    if (sum+num1*2<=n){
     v.push_back(num1);
     num1=num1*2;
     sum=sum+num1;
    }
    else{
     if (sum+num1>n){
      num1=num1*2;
      sum=sum+num1;
      num1=num1/2;
      long long sub=sum-n;
      sum=sum-num1*2;
      if (sub%3){
       if (sub/3+1<=v[v.size()-1]){
        long long num2=num1/2;
        num1=num1/2-sub/3;
        v[v.size()-1]=num1;
        v.push_back(num1+num2-sub%3);
        sum=n;
       }
       else{
        long long num2=v[v.size()-1];
        sum=sum-num2*2;
        long long num4=sum+num2+num2*2-n;
        v[v.size()-1]=0;
        v.push_back(num2-num4);
        sum=n;
       }
      }
      else{
       if (sub/3<=v[v.size()-1]){
        long long num2=v[v.size()-1];
        num1=v[v.size()-1]-sub/3;
        v[v.size()-1]=num1;
        v.push_back(num1+num2);
        sum=n;
       }
       else{
        long long num2=num1/2;
        sum=sum-num2*2;
        long long num4=sum+num2+num2*2-n;
        v[v.size()-1]=0;
        v.push_back(num2-num4);
        sum=n;
       }
      }
     }
     else{
      v.push_back(n-sum-num1);
      num1=n-sum;
      sum=n;
     }
    }
   }
   printf("%d\n",v.size());
   int flag=0;
   for (int i=0;i<v.size();i++){
    if (flag) printf(" ");
    flag=1;
    printf("%lld",v[i]);
   }
   printf("\n");
  }
 }
 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值