Codeforces Round #640 (Div. 4) 全部题解

比赛
难得一见div4的场.也是第一次体会到了AK的快乐(虽然打的是virtual).难度应该在div2的ABC吧.码风以暴力为主.
A - Sum of Round Numbers
题目大题:给一个数,把每一位拆出来.
比如5423拆成 5000 400 20 3
就拆就完事了…
代码

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define pll pair<long long,long long>
#define pdd pair<double,double>
#define db double
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
const int mod = 9901;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
int f[5] = {1,10,100,1000,10000};
int main(){
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		int tn = n;
		int cnt= 0;
		int ans = 0;
		while(tn){
			if(tn%10) ans++;
			tn/=10;
			cnt++;
		}
		int i = 0;
		cout <<ans << endl;
		while(n){
			if(n%10){
				cout << n%10*f[i] << " ";
			}
			n/=10;
			i++;
		}
		cout << endl;
	}
	
	return 0;
}

B - Same Parity Summands
题目大意:给一个n和k 只能用k个奇数或者偶数去凑n.可以重复选同一个数字.
有两种无解的情况
第一种:n是奇数,k是偶数 这种是一定无法解决的.
第二种:如果我们用奇数去凑肯定尽量先用1去凑.如果说n < k的话就凑不出来,偶数同理.
代码

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define pll pair<long long,long long>
#define pdd pair<double,double>
#define db double
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
const int mod = 9901;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
 
int main(){
	int t,n,k;
	cin >> t;
	while(t--){
		cin >> n >> k;
		if((n & 1) == (k & 1)){
			if(n < k){
				puts("NO");
				continue;
			}
			int sum = 0;
			puts("YES");
			fir(i,1,k-1){
				sum += 1;
				cout << 1 << " ";
			}
			cout << n - sum << endl;
		}
		else if((n & 1) && !(k & 1)) puts("NO");
		else{
			if(n < 2*k){
				puts("NO");
				continue;
			}
			puts("YES");
			int sum = 0;
			fir(i,1,k-1){
				sum += 2;
				cout << 2 << " ";
			}
			cout << n-sum << endl;
		}
	}
	
	return 0;
}	

C - K-th Not Divisible by n
题目大意:找第k个不能被n整除的数.
显然出现的频率是n-1,n-1,n-1这样子.就n×k/(n-1) + k%(n-1) .特别是如果n%(n-1) == 0 时 答案是 n×k/(n-1) - 1 具体模拟几个样例就知道答案了.

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define pll pair<long long,long long>
#define pdd pair<double,double>
#define db double
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
const int mod = 9901;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
int t;
int main(){
	cin >> t;
		while(t--){
		int n,k;
		cin >> n >> k;
		int t1 = k/(n-1),t2 = k%(n-1);
		if(!t2) t2--;
		cout << t1*n + t2 << endl;
	}
	
	return 0;
}	

D - Alice, Bob and Candies
题目大意:这题目长的就离谱.就是一个人从头开始吃,一个人从尾开始吃.每次都要吃的比另外一个人多了才停下来,问最后吃了多少次,两个人分别吃了多少.
模拟题,两个指针一指按题目模拟就完事了

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define pll pair<long long,long long>
#define pdd pair<double,double>
#define db double
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
const int mod = 9901;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
 
int a[N];
int main(){
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		fir(i,1,n){
			cin >> a[i];
		}
		int ans = 0,sum1=0,sum2=0,tmp1=0,tmp2=0;
		int i = 0,j = n+1;
		bool f = 1;
		while(i < j-1){
			bool f1 = 0;
			if(f){
				ans++;
				while(!f1 || tmp1 <= tmp2){
					f1 = 1;
					tmp1 += a[++i];
					sum1 += a[i];
					if(i == j-1) break;
				}
				tmp2 = 0;
			}
			else{
				ans++;
				while(!f1 || tmp2 <= tmp1){
					f1 = 1;
					tmp2 += a[--j];
					sum2 += a[j];
					if(i == j-1) break;
				}
				tmp1= 0;
			}
			f = !f;
		}
		cout << ans << " " << sum1 << " " << sum2 << endl;
	}
	
	return 0;
}	

E - Special Elements
题目大意:给n个数,如果一个数可以表示为某个大于2的区间的和,那么他就是特殊元素,问一共有多少个特殊元素.
这题还有点意思.唯一的WA贡献给了这题. 其实不难.我们转化一下问题.先求出前缀和.对每个a[i] 找到一个sum[r]-sum[l] = a[i] 问题就是怎么统计sum[r]-sum[l]了,这里有一个很好的性质.因为数最大不超过8e3.我们用一个数组去存小于8e3的sum[r]-sum[l]就可以了.超过了就舍弃. 虽然是两重循环但是肯定不会循环太多次.

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define pll pair<long long,long long>
#define pdd pair<double,double>
#define db double
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 8e3+10;
const int mod = 9901;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
 
int a[N],s[N],vis[N];
int main(){
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		int ans = 0;
		int mx = 0;
		mem(vis,0);
		fir(i,1,n) cin >> a[i],mx = max(mx,a[i]);
		fir(i,1,n) s[i] = s[i-1] + a[i];
		fir(i,1,n){
			fir(j,i+1,n){
				if(s[j] - s[i-1] > mx) break;
				vis [s[j] - s[i-1]] = 1;
			}
		}
		fir(i,1,n){ 
			if(vis[a[i]]){
				ans++;
			}
		}
		cout <<ans << endl;
	}
	
	return 0;
}	

F - Binary String Reconstruction
题目大意:定义了三种字符串. 00 (01 10)这是同一种. 11 . 给了三种字符串的数量.让你构造一个字符串恰好等于给的数量.
先构造00 再构造 11 最后构造 01 这样一定能构造出答案. 我的代码复杂了一点.判定了 n0 或者 n2 为0的情况 不过也不难构造.纸上模拟一下就好了.

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define pll pair<long long,long long>
#define pdd pair<double,double>
#define db double
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
const int mod = 9901;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
 
int main(){
	int t;
	cin >> t;
	while(t--){
		int a,b,c;
		cin >> a >> b >> c;
		string ans = "";
		if(c){
			if(a){
				fir(i,1,a+1){
					ans += '0';
				}
				b--;
			}
			fir(i,1,c+1){
				ans += '1';
			}
			fir(i,1,b){
				if(i&1) ans += '0';
				else ans +='1';
			}
		}
		else{
			if(a){
				fir(i,1,a+1){
					ans += '0';
				}
				fir(i,1,b){
					if(i&1) ans += '1';
					else ans += '0';
				}
			}
			else{
				fir(i,1,b+1){
					if(i&1) ans += '1';
					else ans += '0';
				}
			}
		}
		cout << ans << endl;
	}
	
	return 0;
}

G - Special Permutation
题目大意:构造一个n的全排列.满足abs(a[i]-a[i+1])绝对值在[2,4]内
暴力构造就好了. 比如n == 12. 1 3 5 7 9 11 8 12 10 6 4 2. 就这样子去构造.先把奇数写完,然后判定一下下面三个偶数要填几.暴力的去填就完事了.我的代码也是突出了一个暴力.

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define pll pair<long long,long long>
#define pdd pair<double,double>
#define db double
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 1e3+10;
const int mod = 9901;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
 
int main(){
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		if(n <=3) puts("-1");
		else if( n== 4) cout << 3 << " " << 1 << " " << 4 << " " << 2 << endl; 
		else{
			vi ans;
			int cnt = 0;
			fir(i,1,n){
				if(i*2 - 1 > n) break;
				ans.pb(i*2-1);
				cnt++;
			}
			if(n&1){
				ans.pb((cnt-2)*2);
				ans.pb((cnt-1)*2);
				cnt--;
			}
			else{
				ans.pb((cnt-2)*2);
				ans.pb((cnt)*2);
				ans.pb((cnt-1)*2);
				cnt --;
			}
			afir(i,cnt-2,1) ans.pb(i*2);
			fir(i,0,ans.size()-1) cout << ans[i] << " ";
			cout << endl;
		}
	}
	
	return 0;
}	

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/106039001