Codeforces Round #640 (Div. 4) (A,B,C,D,E,F,G)

A. Sum of Round Numbers

思路:
应该都会做吧,懒,不写了
代码:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
typedef vector<int> vi;
typedef queue<int> qi;
typedef long long ll;
typedef pair<int, int> pii;
typedef double db;


int main()
{
	int t; cin >> t;
	while (t --)
	{
		int n; cin >> n;
		vi ans;
		int t = 1;
		while (n)
		{
			if(n % 10 != 0)
				ans.pb(n % 10 * t);
			t *= 10;
			n /= 10;
		}
		cout << ans.size() << endl;
		for (auto &x : ans) cout << x << " ";
		cout << endl;
	}

	return 0;
}

B. Same Parity Summands

思路:
两种情况:

  1. 都是奇数,k - 1个1,剩下一个数是 n - (k - 1)
  2. 都是偶数,k - 1个2,剩下一个数是n - (k - 1) * 2
  3. 判断上面两个是否合法,合法就输出yes,不然就no
    代码:
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
typedef vector<int> vi;
typedef queue<int> qi;
typedef long long ll;
typedef pair<int, int> pii;
typedef double db;


int main()
{
	int t; cin >> t;
	while (t --)
	{
		int n, k; cin >> n >> k;
		if(n > k - 1 && (n - (k - 1)) % 2 == 1)
		{
			puts("YES");
			for (int i = 1; i < k; ++ i) cout << 1 << " ";
			cout << n - (k - 1)  << endl;
		}
		else if(n > (k - 1) * 2 && (n - (k - 1) * 2) % 2 == 0)
		{
			puts("YES");
			for (int i = 1; i < k; ++ i) cout << 2 << " ";
			cout << n - (k - 1) * 2 << endl;
		}
		else puts("NO");
	}

	return 0;
}

C. K-th Not Divisible by n

思路:
看看题目给得样例,可以看出每个n个数里面就有n-1个是不能整除n的,所以 x ∗ n x*n xn x ∗ ( n − 1 ) x*(n-1) x(n1)合法的,所以肯定存在一个x使得 x ∗ ( n − 1 ) ≤ k x*(n-1)\leq k x(n1)k ( x + 1 ) ∗ ( n − 1 ) > k (x+1)*(n-1)>k (x+1)(n1)>k,所以第 k k k个数就在这两者之间,二分找到这个x,就知道第 k k k个数了。
特判这总情况: x ∗ n = k x*n=k xn=k,则答案就是 n ∗ k − 1 n*k-1 nk1
代码:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
typedef vector<int> vi;
typedef queue<int> qi;
typedef long long ll;
typedef pair<int, int> pii;
typedef double db;


int main()
{
	int t; cin >> t;
	while (t --)
	{
		ll n, k; cin >> n >> k;
		ll l = 0, r = 1e9;
		while (l < r)
		{
			ll mid = (l + r + 1) >> 1;
			if(mid * (n - 1) <= k) l = mid; else r = mid - 1;
		}
		int f = 0;
		if(k - (l * (n - 1)) == 0) f = 1;
		cout << l * n + (k - (l * (n - 1))) - f << endl;
	}

	return 0;
}

D. Alice, Bob and Candies

思路:
额。模拟题,这个没啥好说的了,模拟Alice吃一口,Bob吃一口,一直吃下去就行了
代码:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
typedef vector<int> vi;
typedef queue<int> qi;
typedef long long ll;
typedef pair<int, int> pii;
typedef double db;
const int N = 2e5 + 5;
int A[N];

int main()
{
	int t; scanf("%d", &t);
	while (t --)
	{
		int moves = 0, a = 0, b = 0;
		int n; scanf("%d", &n);
		for (int i = 1; i <= n; ++ i) scanf("%d", &A[i]);
		
		int pa = 1, pb = n, sa = 0, sb = 0, f = 1;
		while (pa <= pb)
		{
			if(f == 1)
			{
				sa = 0;
				while (sa <= sb && pa <= pb)
				{
					sa += A[pa ++];
				}
				a += sa;
				f = 0;
//				cout << sa << endl;
			}
			else 
			{
				sb = 0;
				while (sb <= sa && pa <= pb)
				{
					sb += A[pb --];
				}
				b += sb;
				f = 1;
//				cout << "sb : " <<sb << endl;
			}
			++ moves;
		}
		printf("%d %d %d\n", moves, a, b);
	}

	return 0;
}

E. Special Elements

解法1

思路:
用set维护前缀和,对于每i位,然后对于每个特殊元素,查找set中是否存在值等于 s u m [ i ] − x sum[i]-x sum[i]x的前缀和 s u m [ j ] , j < i − 1 sum[j],j<i-1 sum[j],j<i1,则可以判断了,时间时间复杂度为 O ( n ∗ p ∗ l o g ( n ) ) O(n*p*log(n)) O(nplog(n))
代码:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
typedef vector<int> vi;
typedef queue<int> qi;
typedef long long ll;
typedef pair<int, int> pii;
typedef double db;
const int N = 8e3 + 5;
int a[N], sum[N], b[N];
int ct[N];
set<int> m;

int main()
{
	int t; cin >> t;
	while (t --)
	{
		m.clear();
		memset(ct, 0, sizeof(ct));
		int n; cin >> n;
		for (int i = 1; i <= n; ++ i)
		{
			cin >> a[i];
			b[i] = a[i];
			ct[a[i]] ++;
		}
		sort (b + 1, b + n + 1);
		int p = unique(b + 1, b + n + 1) - b;
		int ans = 0;
		for (int i = 1; i <= n; ++ i)
		{
			sum[i] = sum[i - 1] + a[i];
			for (int j = 1; j < p; ++j)
			{
				if(!ct[b[j]]) continue;
				if(m.size() && m.find(sum[i] - b[j]) != m.end())
				{
					ans += ct[b[j]];
					ct[b[j]] = 0;
				}
			}
			m.insert(sum[i - 1]);
		}
		cout << ans << endl;
	}

	return 0;
}

解法2

思路:
n n n最大是 8000 8000 8000,所以 n 2 n^2 n2的做法也是可以的,枚举所有长度大于 1 1 1的区间,可以利用前缀和 O ( 1 ) O(1) O(1)求出区间和,最后扫一遍就可以了,时间复杂度为 O ( n 2 ) O(n^2) O(n2)
代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 8e3 + 5;
bool v[N];
int a[N], s[N];
int main()
{
	int t; cin >> t;
	while (t --)
	{
		memset(v, 0, sizeof(v));
		int n; cin >> n;
		for (int i = 1; i <= n; ++ i)
		{
			cin >> a[i];
			s[i] = s[i - 1] + a[i];
		}
		for (int l = 1; l <= n; ++ l)
			for (int r = l + 1; r <= n; ++ r)
				if(s[r] - s[l - 1] <= 8000)
					v[s[r] - s[l - 1]] = 1;
		int ans = 0;
		for (int i = 1; i <= n; ++ i) ans += v[a[i]];
		cout << ans << endl;
	}
	
	return 0;
}

F. Binary String Reconstruction

比赛的时候时间不够了,没开出来,吐血。
思路:
直觉感觉就是这个字符串就是这样,左边全是0,中间就是0101这样,右边都是1,只需控制好数量就行了。

  1. n 1 > 0 n1>0 n1>0 的情况,就是上面说的那种
  2. n 1 = 0 n1 = 0 n1=0的情况,要不就是 n 0 + 1 n_0+1 n0+1个0,要不就是 n 2 + 1 n_2+1 n2+1个1
    重点说一下第1种情况,可以先构造中间01块的数量,只构造到01…01就可以了,不要以0结尾这样后面接1会导致 n 2 n_2 n2的数量不够,剩下的一个0等到右边的所有1放完,放到最后去。然后就是左边放 n 0 n_0 n0个0,右边放 n 2 n_2 n2个1,最后特判要不放0就行了
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
typedef vector<int> vi;
typedef queue<int> qi;
typedef long long ll;
typedef pair<int, int> pii;
typedef double db;
const int N = 605;
char a[N];

int main()
{
	int t; cin >> t;
	while (t --)
	{
		int n0, n1, n2; cin >> n0 >> n1 >> n2;
		if(!n1)
		{
			if(n0) for (int i = 0; i <= n0; ++ i) putchar('0');
			if(n2) for (int i = 0; i <= n2; ++ i) putchar('1');
		}
		else
		{
			int f = 0;
			if(n1 % 2 == 0) f = 1,n1 --;  
			int j, i;
			for (i = 0, j = 200; i <= n1; ++ i, ++ j) 
				if(j % 2) a[j] = '1';
				else a[j] = '0';
			for (i = 1; i <= n2; ++ i, ++ j) a[j] = '1';
			if(f) a[j ++] = '0';
			a[j] = '\0';
			for (i = 1, j = 199; i <= n0; ++ i, -- j) a[j] = '0';
			++ j;
//			puts(a + j);
			for (i = j; a[i]; ++ i) putchar(a[i]);
			
		}
		puts("");
	}

	return 0;
}

G. Special Permutation

这种构造题有想法后真的简单,可能很多人被E题卡了,都没时间做这题,才导致过题人数比较少。

思路:
想一想这样一个序列 1 , 3 , 5... ( 2 ∗ n − 1 ) 1,3,5...(2*n-1) 1,3,5...(2n1) 2 , 4 , 6.. ( 2 ∗ n ) 2,4,6..(2*n) 2,4,6..(2n)两个序列,前一个元素和后一元素之差都是2,这是符合题目要求的,所以可以把第2块调个顺序,然后把它两连在一起,这样就只有连接处不合法。

  1. n n n是偶数,连接处是这样的 . . . ( 2 k − 3 ) , ( 2 k − 1 ) , ( 2 k ) , ( 2 k − 2 ) . . . ...(2k-3),(2k-1),(2k),(2k-2)... ...(2k3),(2k1),(2k),(2k2)...,调换 ( 2 k − 3 ) (2k-3) (2k3) ( 2 k − 1 ) (2k-1) (2k1)就可以了
  2. n n n是奇数,连接处是这样的 . . . ( 2 k − 1 ) , ( 2 k + 1 ) , ( 2 k ) , ( 2 k − 2 ) . . . ...(2k-1),(2k+1),(2k),(2k-2)... ...(2k1),(2k+1),(2k),(2k2)...,调换 ( 2 k − 2 ) (2k-2) (2k2) ( 2 k ) (2k) (2k)就可以了

代码:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
typedef vector<int> vi;
typedef queue<int> qi;
typedef long long ll;
typedef pair<int, int> pii;
typedef double db;
const int N = 1e3 + 5;
int a[N];

int main()
{
	int t; cin >> t;
	while (t --)
	{
		int n; cin >> n;
		if(n < 4)
		{
			puts("-1");
			continue;
		}
		int num = (n + 1) / 2;
		for (int i = 1, j = 1; i <= num; ++ i, j += 2) a[i] = j;
//		swap(a[num], a[num - 1]);
		for (int i = num + 1, j = 2; i <= n; ++ i, j += 2) a[i] = j;
		reverse(a + num + 1, a + n + 1);
		if(n % 2 == 0) swap(a[num], a[num - 1]);
		else swap(a[num + 1], a[num + 2]);
		for (int i = 1; i <= n; ++ i) printf("%d%c", a[i], i == n ? '\n' : ' ');
		
	}

	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值