zoukankan      html  css  js  c++  java
  • 习题训练一 题解

    A - Phoenix and Balance

     1.题意

      给定n个硬币(n为偶数),硬币的质量分别为2^1,2^2,2^3,······,2^n,要求把硬币分成数量相同的两部分使得两部分硬币的质量和之差最小,输出质量和之差。

     2.题解

      数学太菜了,不会推演,只能找规律。当n为2时,ans = 2^1;当n为4时,ans = 2^1+2^2;当n为6时,ans = 2^1+2^2+2^3;即ans = 2^1+2^2+···+2^(n/2)。

     3.代码

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const ll maxn = 1e8 + 5;
    int t,n;
    int main(){
    	cin >> t;
    	while(t--) {
    		cin >> n;
    		ll ans = 0;
    		for(int i = 1;i <= n/2;i++) {
    			ans += (ll)pow(2 , i);
    		}
    		cout << ans <<endl;
    	}	
    	
    	return 0; 
    }
    

      

    B - Phoenix and Beauty

     1.题意

      给定两个整数n和k,再给一个长度为n的数列,要求往数列中插入不限个数个不大于n的数字,使得数列每k个连续的数的和都相同。

     2.题解

      把数列改造成以k个数字为单位,循环n遍(因为如果数列中有两个相同的数字,就要循环两次,所以最多循环n次)的数列即可,循环节用vector集合储存比较方便。当数列的数字种数等于k时,把数列中的数字循环即可,例:n = 4, k = 2, 数列:1 2 2 1, 输出:1 2 1 2 1 2 1 2 ; 当数列的数字种数小于k时,就要遍历0到n,补上(k - 数列中数字种数)个数列中没出现过的数字,例:n = 4, k = 3, 数列:1 2 2 1, 输出:1 2 3 1 2 3 1 2 3 1 2 3 ; 而如果数列的数字种数大于k,例:n = 3, k = 2, 数列:1 2 3,无解,输出 -1。

     3.代码

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const ll maxn = 1e8 + 5;
    int t,n,k;
    int main(){
    	cin >> t;
    	while(t--) {
    		cin >> n >> k;
    		int a[n + 1] = {0};
    		vector <int> num;  
    		int cnt = 0;
    		int x;
    		for(int i = 1;i <= n;i++) {
    			cin >> x;
    			if(a[x] == 0) {				
    				cnt++;
    				num.push_back(x);
    			}
    			a[x] = 1;		
    		}
    		if(cnt < k) {	
    			for(int i = 1, cha = 1;i <= n, cha <= k - cnt; i++) {
    				if(a[i] == 0) {
    					cha++;
    					num.push_back(i);
    				}
    			}
    		
    		}
    		
    		if(cnt > k) {				
    			cout << -1 << endl;
    			continue;
    		}
    		else {
    			cout << n * num.size() << endl;
    			for(int i = 0;i < n;i++) {
    				for(int j = 0;j < num.size();j++) {
    					if(i == 0&&j == 0) {
    						cout << num[j];
    					}
    					else {
    						cout << ' ' << num[j];
    					}	
    				}
    			}
    		}
    		cout << endl;
    	}	
    	
    	return 0; 
    } 
    

      

    C - Road To Zero

     1.题意

      给定两个整数x, y,把这两个数字同时+1或-1的代价是b,把这两个数字中的一个数字+1或-1的代价是a,求将两个数字都变为0的最小代价。

     2.题解

      先把x, y化为绝对值(因为+或-是等效的),再把两个数排序,让x成为较小数(方便后面计算),如果b < 2*a,ans = x * b + (y - x) * a ; 否则只用a,ans = (x + y) * a(没考虑b < a的情况,也能过,题目应该默认了b > a)。

     3.代码

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const ll maxn = 1e8 + 5;
    int t;
    int main(){
    	cin >> t;
    	while(t--) {
    		ll x, y, a, b;
    		cin >> x >> y;
    		
    		x = abs(x);
    		y = abs(y);
    		if(x > y) {
    			ll temp = x;
    			x = y;
    			y = temp;
    		}
    		cin >> a >> b;
    		
    		if(!x && !y) {
    			cout << 0 << endl;
    			continue;
    		}
    		ll ans = 0;
    		if(b < 2 * a) {	
    			ans += x * b;
    			ans += (y - x) * a;		
    		}
    		else {
    			ans += (x + y) * a;
    		}
    		cout << ans << endl;
    	}	
    	
    	return 0; 
    } 
    

     

    D - Binary Period 

     1.题意

      给定一个只由0和1构成的字符串s,要求构造一个字符串t,使得s是t的字串,并且t的循环节尽量小,t的长度不能超过s的两倍。

     2.题解

      与B题类似,不能超过s长度的两倍,就把t构造成s的两倍。如果s全为0或全为1,那么t也全为0或全为1;如果s有0也有1,那么t就为01串循环。

     3.代码

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const ll maxn = 1e8 + 5;
    int t;
    int main(){
    	cin >> t;
    	while(t--) {
    		string s;
    		cin >> s;
    		
    		int flag_0 = 1;
    		int flag_1 = 1;
    		for(int i = 0; i < s.size(); i++) {
    			if(s[i] == '1') {
    				flag_0 = 0;
    				break;
    			}
    		}
    		for(int i = 0; i < s.size(); i++) {
    			if(s[i] == '0') {
    				flag_1 = 0;
    				break;
    			}
    		}
    		
    		if(flag_0) {	
    			for(int i = 0; i < 2 * s.size(); i++) {
    				cout << 0;
    			}
    			cout << endl;
    		}	
    		else if(flag_1) {	
    			for(int i = 0; i < 2 * s.size(); i++) {
    				cout << 1;
    			}
    			cout << endl;
    		}
    		else {
    			for(int i = 0; i < 2 * s.size(); i++) {
    				if(i % 2) {
    					cout << 1;
    				}	
    				else {
    					cout << 0;
    				}
    			}
    			cout << endl;
    		}
    	}	
    	
    	return 0; 
    } 
    

      

    E - Nastya and Rice

     1.题意

      给定n个范围在[a - b, a + b]的数,问这些数的和是否在[c -d, c + d]范围中,满足输出“Yes”,否则输出“No”(a > b, c > d)。

     2.题解

      利用端点判断即可。

     3.代码

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const ll maxn = 1e8 + 5;
    int t;
    int main(){
    	cin >> t;
    	while(t--) {
    		int n, a, b, c, d;
    		cin >> n >> a >> b >> c >> d;
    		
    		if(((a - b) * n <= c + d) && ((a + b) * n >= c - d)) {	
    			cout << "Yes" << endl;
    		}	
    		else {
    			cout << "No" << endl;
    		}
    	}	
    	
    	return 0; 
    } 
    

      

    F - Nastya and Door

     1.题意

      给定n个数组成数列,求长度为k的子数列的极大值的数量最多有多少。

     2.题解

      先统计极大值的位置,开数组前缀和记录极大值的数量,以1到n - k + 1为左边界,k为区间长度,维护区间极大值的最大数量。

     3.代码

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const ll maxn = 2e5 + 5;
    int t;
    int main(){
    	cin >> t;
    	while(t--) {
    		int n, k;
    		int a[maxn];
    		cin >> n >> k;
    		for(int i = 1; i <= n; i++) {
    			cin >> a[i];
    		}
    		
    		for(int i = 2; i < n; i++) {
    			if(a[i] >= a[i - 1] && a[i] >= a[i + 1]) {
    				a[i] = -1;
    				i++;
    			}
    		}
    		int pr[maxn] = {0, 0};
    		for(int i = 2; i < n; i++) {
    			pr[i] += pr[i - 1];
    			if(a[i] == -1) {
    				pr[i]++;
    			}
    		}
    		pr[n] = pr[n - 1];
    	
    		int cnt = 0;
    		int mmax = 0;
    		int l = 1;
    		for(int i = 1; i + k <= n + 1; i++) {
    			cnt = pr[i + k - 2] - pr[i];
    			if(cnt > mmax) {
    				mmax = cnt;
    				l = i;
    			}
    		}
    		cout << mmax + 1 << ' ' << l << endl;
    	}	
    	
    	return 0; 
    } 
    

      

  • 相关阅读:
    poj 2411 Mondriaan's Dream 骨牌铺放 状压dp
    zoj 3471 Most Powerful (有向图)最大生成树 状压dp
    poj 2280 Islands and Bridges 哈密尔顿路 状压dp
    hdu 3001 Travelling 经过所有点(最多两次)的最短路径 三进制状压dp
    poj 3311 Hie with the Pie 经过所有点(可重)的最短路径 floyd + 状压dp
    poj 1185 炮兵阵地 状压dp
    poj 3254 Corn Fields 状压dp入门
    loj 6278 6279 数列分块入门 2 3
    VIM记事——大小写转换
    DKIM支持样本上传做检测的网站
  • 原文地址:https://www.cnblogs.com/lvguapi/p/12914729.html
Copyright © 2011-2022 走看看