Codeforces Round #640(div.4) 题解

A. Sum of Round Numbers

​ 将某个整数,分解为最少个数的形如x000的数之和(1 <= x <= 9,x右侧0的个数 >= 0).

  • 直接从个位开始拆,当某位上数字非0时记录。
	cin >> t;
	while(t--){
		idx = 0,a = 1;
		cin >> n;
		while(n){
			if(n % 10) book[idx++] = (n % 10) * a;
			a *= 10;
			n /= 10;
		}
		cout << idx << endl;
		for(int i = 0; i < idx; i++){
			cout << book[i] << ' ';
		}
		if(t) cout << endl;
	}
B. Same Parity Summands

​ 给你一个整数n,要求拆成k个奇数或者k个偶数的和

  • n为奇数,只有奇数才可以凑出来
    • 判断k的奇偶性,k 是否大于n,前k - 1个奇数使用1,计算最后一个奇数的值
  • n为偶数
    • 偶数个奇数 - k是否大于n,前k - 1个奇数使用1,计算最后一个奇数的值
    • 偶数 -- 判断2 * k是否大于n,前k - 1个偶数使用2,计算最后一个偶数
	cin >> t;
	while(t--){
		cin >> n >> k;
		if(n & 1){//奇数 奇数 
			if(k & 1 && k <= n){
				cout << "YES" << endl;
				for(int i = 0; i < k - 1; i ++) cout << "1 ";
				cout << n - k + 1 << endl;
			}else cout << "NO" << endl;
		}else{
			if(2 * k <= n){//偶数 奇数个 只能用偶数 偶数个 均可 
				cout << "YES" << endl;
				for(int i = 0; i < k - 1; i++) cout << "2 ";
				cout << n - (k - 1) * 2 << endl;				
			}else if(!(k & 1) && k <= n){
				cout << "YES" << endl;
				for(int i = 0; i < k - 1; i++) cout << "1 ";
				cout << n - k + 1 << endl;
			}else cout << "NO" << endl;
		}
	}
C.K-th Not Divisible by n

​ 输入n,寻找第k个不能被n整除的数

  • 从1开始,每n个数一组,每组中均有n - 1个数不可以被n整除
  • 当k可以整除n - 1,第k个为 n * k - 1
  • 第k个为k + i (i = k / (n - 1)): i * n + k - i * (n - 1) = k + i
	cin >> t;
	while(t--){
		cin >> n >> k;
		i = k / (n - 1);//每n个数you n-1个 
		if(i * (n - 1) == k) cout << n * i - 1 << endl;
		else cout << k + i << endl;
	}
D. Alice, Bob and Candies

​ 模拟,a and b每次吃的糖果总大小要最大且吃的糖果个数尽可能少。

	cin >> t;
	while(t--){
		cin >> n;
		vector<int> ar(n);
		for(int i = 0;i < n; i++) cin >> ar[i];
		i = st = 0;//st 吃糖果次数 i j :a b的索引
		j = n - 1;
		s_a = s_b = mx = 0;//s_a,s_b:a,b吃的所有糖果的总大小
		while(i <= j){
			a = 0;//a这一次吃的糖果总大小
			++st;
			for(; i <= j && a <= mx; i++) a += ar[i];
			s_a += a;
			if(a > mx) mx = a;
			if(i > j) break;
			b = 0;//b
			++st;
			for(; j >= i && b <= mx; j--) b += ar[j];	
			s_b += b;
			if(b > mx) mx = b;
			if(i > j) break;
		}
		cout << st << ' ' << s_a << ' ' << s_b << endl;
	}
E.Special Elements

​ 一个数组中,存在一些特殊元素:数组中存在一些区间和 == a[i];求出数组中特殊元素个数。

  • 1 <= n <= 8000,1 <= a[i] <= n
  • n最大直到8000,所以O(n^2)以内的算法均可。
  • 使用前缀和,直接计算所有的区间和,同时判断是否 <= n,若是,则记录下来(记录数组范围 <= n)
  • 遍历数组,计算数组中有多少个元素被记录
int ans,t,v,n,a[8010],s[8010],book[8010];//需要处理的最大范围:[1,8000] 
//数据量很小,暴力+前缀和 记录所有的长度大于2的子序列和 找符合条件的 
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		ans = s[0] = 0;
		memset(book,0,sizeof(book));
		cin >> n;
		for(int i = 1; i <= n; i++){//索引从1开始,避免处理边界问题
			cin >> a[i];
			if(i > 1){
				s[i] = s[i - 1] + a[i];
				for(int j = 0; j < i - 1; j++){//r - l >= 2
					v = s[i] - s[j];
					if(v <= n && !book[v]) book[v] = 1;
				} 
			}else s[i] = a[i];
		}
		for(int i = 1; i <= n; i++) if(book[a[i]]) ++ans;
		cout << ans << endl;
	}
	return 0;
} 
F. Binary String Reconstruction

​ 输入n0,n1,n2分别代表"00","01","11"串的个数。构造含有这些子串的01串。

  • 首先,如果n1 == 0。结果只会是00.. or 11.. 串(n0 +1 or n2 + 1个)

  • n1不为0时,先生成00串(n0 + 1个 0),再加上01串(n0为0,先添加一个0;交替添加n1个 1 or 0)

  • 最后,添加11串。在之前生成的字符串中找到最后一个1所在位置,插入n2个1。(插入到其它1所在的位置也可以)

string s;
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin >> n0 >> n1 >> n2;
		if(!n1){//不存在01则n0 or n1有一个也为0 
			if(!n0) cout << string(n2 + 1,'1');//n2 + 1
			else cout << string(n0 + 1,'0');//n0 + 1
			cout << endl;
			continue;
		}
		s = "";
		if(n0) s = string(n0 + 1,'0');
		//01010...  n1奇偶性不同最终结尾数字不同 -- 把11串插到1相邻位置中间 
		if(!n0) s += '0';//n0为0,补一个0 
		for(int i = 0; i < n1; i++){
			if(i & 1) s += '0';
			else s += '1';
		}
		if(n2){
			string a = string(n2,'1');
			//11串有n2对 n2 + 1个 
			//for(int i = 0; i < n2; i++) a += '1';
			if(s[s.length() - 1] == '1') s += a;
			else s.insert(s.length() - 2,a);
		} 
		cout << s << endl;	
	}
	return 0;
} 
G. Special Permutation

​ 长为n的数组中,1~n每个数字只出现一次,在这个数组中,相邻元素差的绝对值的范围[2,4]。

  • 贪心:
    • n < 4,无解
    • 从大到小输出小于等于n的所有奇数。
    • 输出“4 2”
    • 输出所有小于等于n的偶数
    • method2::先输出偶数,但是n == 4的时候需要特判,之后输出"5,1,3",其它奇数升序
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin >> n;
		if(n < 4) cout << "-1";
		else{
			s = n;
			if(!(s & 1)) --s;//先奇数
			while(s > 0){
				cout << s << ' ';
				s -= 2;
			} 
			cout << "4 2";
			s = 6;
			while(s <= n){
				cout << ' ' << s;
				s += 2;
			}
		}
		cout << endl;
	}
	return 0;
} 
原文地址:https://www.cnblogs.com/honey-cat/p/12872577.html