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

E. Sum of Digits
原题目
由于k<=9,所以[x,x+k]中至多产生一次进位。如果是类似于199进位到200,则f(200)-f(199)=-17,发生一次进位损失太大,不可能在这种情况下取到最小值。因此发生进位时,十位数字最大为8(xxx8x),这样才能保证十位进位后,不会导致百位也发生进位。
现在枚举个位数字,假设个位为m,其余位相加的和为a。

  1. 当不发生进位时,即m+k<=9时。
    此时有(k+1)a+(m+m+k)(k+1)/2=n
    a=(n-(m+m+k)(k+1)/2)/(k+1)。
    m越大,a越小,则总体越小。因此将m从9到0进行遍历,找到最先满足的a。由于此时不会产生进位,所以每一位最大的取值为9。
    满足条件最小的x应形如:y9…9m。y+9+…+9=a。
  2. 发生进位,即m+k>9时
    此时有(m+9)(10-m)/2+(k+m-9)(k+m-10)/2+(10-m)a+(k+m-9)(a+1)=n
    可以解出a与m的关系,简记为a=t+pm。m越小,a越小。因此从0到9遍历,找到最先满足条件的a。由于会产生进位,因此需要保证十位最大为8.
    满足条件最小的x应形如:y9…98m。y+9+…+9+8=a。
#include 
using namespace std;

int main(){
	int t;
	scanf("%d",&t);
	for(int i=0;i<t;i++){
		int n,k,ta=1e8,tb=1e8;
		scanf("%d%d",&n,&k);
		stack<int> pre;
		stack<int> pos;
		for(int x=9;x>=0;x--){
			if(x+k<=9){
				int res=n-(2*x+k)*(k+1)/2;
				if(res>=0&&res%(k+1)==0){
					pre.push(x);
					int a=res/(k+1);
					ta=a;
					while(a>9){
						a-=9;
						pre.push(9);
					}
					if(a!=0){
						pre.push(a);
					}
					break;
				}
			}
		}
		for(int x=1;x<=9;x++){
			if(x+k>9){
				int res=n-((x+9)*(10-x)/2+(k+x-9)*(k+x-10)/2+k+x-9);
				if(res>=0&&res%(k+1)==0){
					int a=res/(k+1);
					tb=a;
					pos.push(x);
					if(a>=9){
						pos.push(8);
						a-=8;
					}
					while(a>9){
						a-=9;
						pos.push(9);
					}
					if(a!=0){
						pos.push(a);
					}
					break;
				}
			}
		}
		if(pre.empty()&&pos.empty()){
			printf("-1\n");
		}
		else{
			if(ta<=tb){
				while(!pre.empty()){
					printf("%d",pre.top());
					pre.pop();
				}
				printf("\n");
			}
			else{
				while(!pos.empty()){
					printf("%d",pos.top());
					pos.pop();
				}
				printf("\n");
			}
		}
	}
	
	
	return 0;
}

F. Network Coverage
原题目
由于城市是圆环,所以可以任取一个城市,将该城市作为起点,把这个圆环展开。
假设有四个城市,四个连接站。从第二个城市开始,如果每个城市都优先占用其左侧的连接站,这样就能保证右边连接站剩下的空间最大,更有可能满足下一个城市的需求。
Educational Codeforces Round 90 (Rated for Div. 2)EF题解_第1张图片
而唯一需要特殊判断的就是1号城市,由于先前的策略,4号连接站剩下了最大空间,但此时1号连接站却并不是最佳的空间。比如,当1号连接站放满,但2号连接站仍有空间,我们可以选择调整2号城市的分布,把2号连接站填满,1号连接站产生空余。如果要调整2号城市的分布,首先就要保证在1号连接站中,有2号城市。
设pre[j]为j号城市在j-1连接站中占有的数量。bi[j]为j号连接站多出的空间。
则有bi[j-1]+=min(pre[j],bi[j]);
从后往前扫描一遍,即可得到1号连接站最多剩余的空间。
此时再判断1号城市是否满足要求即可。
Educational Codeforces Round 90 (Rated for Div. 2)EF题解_第2张图片

#include
using namespace std;
long long ai[1000005],bi[1000005],pre[1000005];
int main(){
	int t;
	scanf("%d",&t);
	for(int i=0;i<t;i++){
		int n;
		bool flag=true;
		scanf("%d",&n); 
		for(int j=0;j<n;j++){
			scanf("%lld",&ai[j]);
		}
		for(int j=0;j<n;j++){
			scanf("%lld",&bi[j]);
		}
		long long tmp=bi[0];
		for(int j=1;j<n;j++){
			if(bi[j-1]+bi[j]<ai[j]){
				flag=false;
				break;
			}
			else{			
				if(bi[j-1]>=ai[j]){
					pre[j]=ai[j];
					bi[j-1]-=ai[j];
				}
				else{
					pre[j]=bi[j-1];
					bi[j]=bi[j]+bi[j-1]-ai[j];
					bi[j-1]=0;
				}
			}
		}
		if(flag){
			for(int j=n-2;j>0;j--){
				if(bi[j]==0||(bi[j]!=0&&pre[j]==0)){
					continue;
				}
				bi[j-1]+=min(pre[j],bi[j]);				
			}
			if(bi[0]+bi[n-1]>=ai[0]){
				printf("YES\n");
			}
			else{
				printf("NO\n");
			}
		}
		else{
			printf("NO\n");
		}
	}
	
	return 0;
}

你可能感兴趣的:(算法,c++,icpc,acm竞赛,贪心算法)