Codeforces Round #690 (Div. 3)A-E2

The title is too long, so skip it in the blog. . If you need a question surface, please click Codeforces Round #690 (Div. 3)
As the author is limited, write the answer to question A-E1 first.
update: The E2 problem solution has been updated.
A.Favorite Sequence
Idea: Obviously, we need to output the first one and the next one for the given sequence each time, and we need to judge the parity of n.

#include <bits/stdc++.h>

using namespace std;

int t, n;
int a[10000010];

int main(){
    
    
	scanf("%d", &t);
	while(t--){
    
    
		scanf("%d", &n);
		for(int i = 1; i <= n; i++){
    
    
			scanf("%d", &a[i]);
		}
		for(int i = 1; i <= n / 2; i++){
    
    
			printf("%d %d ", a[i], a[n + 1 - i]);
		}
		if(n % 2 == 1) printf("%d", a[n / 2 + 1]);
		printf("\n");
	}
	return 0;
}

B. Last Year's Substring
idea: According to the meaning of the question, only strings constructed in the form of 2020xxx, 202xxx0, 20xxx20, 2xxx020, xxx2020 can be changed to 2020 in zero or one operation.

#include <bits/stdc++.h>

using namespace std;

int t, n;
char c[210];

int main(){
    
    
	scanf("%d", &t);
	while(t--){
    
    
		int flag = 0;
		scanf("%d", &n);
		for(int i = 1; i <= n; i++){
    
    
			cin >> c[i];
		}
		if(flag == 0){
    
    
			if(c[1] == '2' && c[2] == '0' && c[3] == '2' && c[4] == '0') flag = 1;
		}
		if(flag == 0){
    
    
			if(c[n - 1] == '2' && c[n - 2] == '0' && c[n - 3] == '2' && c[n] == '0') flag = 1;
		}
		if(flag == 0){
    
    
			if(c[1] == '2' && c[n - 2] == '0' && c[n - 1] == '2' && c[n] == '0') flag = 1;
		}
		if(flag == 0){
    
    
			if(c[1] == '2' && c[2] == '0' && c[n - 1] == '2' && c[n] == '0') flag = 1;
		}
		if(flag == 0){
    
    
			if(c[1] == '2' && c[2] == '0' && c[3] == '2' && c[n] == '0') flag = 1;
		}
		if(flag == 1) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

C. Unique Number
idea: when n=45, it is 123456789, which is the largest number that meets the conditions, so when n>45, output -1. When n<=45, construct the string, because the requirement is the smallest, so the output should be output in reverse order.

#include <bits/stdc++.h>

using namespace std;

int t, n;
int a[10000010];

int main(){
    
    
	scanf("%d", &t);
	while(t--){
    
    
		scanf("%d", &n);
		if(n > 45) printf("-1\n");
		else{
    
    
			int temp = 9, cnt = 0;
			while(n > temp){
    
    
				n -= temp;
				a[++cnt] = temp;
				temp--;
			}
			a[++cnt] = n;
			for(int i = cnt; i >= 1; i--){
    
    
				printf("%d", a[i]);
			}
		}
		printf("\n");
	}
	return 0;
}

D. Add to Neighbour and Remove
idea: use sum to record the sum, and experiment with every possibility of violence from large to small.

#include <bits/stdc++.h>

using namespace std;

int t, n;
int a[3010];

int main(){
    
    
	scanf("%d", &t);
	while(t--){
    
    
		long long sum = 0;
		scanf("%d", &n);
		for(int i = 1; i <= n; i++){
    
    
			scanf("%d", &a[i]);
			sum += a[i];
		}
		for(int i = n; i >= 1; i--){
    
    
			long long cnt = 0;
			if(sum % i != 0) continue;
			long long temp = sum / i;
			long long ans = 0;
			for(int j = 1; j <= n; j++){
    
    
				ans += a[j];
				if(ans == temp){
    
    
					cnt++;
					ans = 0;
				}
				else if(ans > temp) break;
			}
			if(cnt == i){
    
    
				printf("%d\n", n - i);
				break;
			}
		}
	}
	return 0;
}

E1 .Close Tuples (easy version)
idea: simple combinatorial mathematics problem, use map to record the number of each number, there are several possibilities, m[i] choose three, m[i] choose two m[ Choose one from i+1] or choose one from m[i+2], choose one from a[i] choose one from a[i+1] choose one from a[i+2] or choose one from a[i] a[i+1 ] Choose two or one of a[i] and a[i+2] choose two. Clearing the array with memset will be at the ninth point tle, so you need to clear the used m[i] easily so that it will not time out!

#include <bits/stdc++.h>

using namespace std;

long long t, n;
long long a[200010], m[200010], ma[200010];
long long ca(long long x){
    
    
	return x;
}
long long cb(long long x){
    
    
	return x * (x - 1) / 2;
}
long long cc(long long x){
    
    
	return x * (x - 1) * (x - 2) / 6;
}

int main(){
    
    
	scanf("%lld", &t);
	while(t--){
    
    
		long long sum = 0;
		scanf("%lld", &n);
		for(int i = 1; i <= n; i++){
    
    
			scanf("%lld", &a[i]);
		}
		for(int i = 1; i <= n; i++){
    
    
			m[a[i]]++;
		}
		for(int i = 1; i <= n; i++){
    
    
		
			long long ans1 = cc(m[i]);
			long long ans2 = cb(m[i]) * (ca(m[i + 1]) + ca(m[i + 2]));
			long long ans3 = ca(m[i]) * (cb(m[i + 1]) + cb(m[i + 2]) + (ca(m[i + 1]) * ca(m[i + 2])));
			sum += ans1 + ans2 + ans3;
			m[i]=0;
		}
		printf("%lld\n", sum);
	}
	return 0;
}

E2. Close Tuples (hard version)
idea: Both the simple version and the simple version are combination numbers, but the hard version needs to use division to take the modulus, so you can use Fermat's little theorem to find the inverse element to find the combination number.

#include <bits/stdc++.h>
#define ll long long

using namespace std;
const ll mod = 1e9 + 7;
const int maxn = 2e5 + 10; 
ll f[maxn];
ll a[maxn];
int t, n, m, k;

ll qpow(ll a, ll b){
    
    
	ll ans = 1;
	while(b){
    
    
		if(b & 1) ans = ans * a % mod;
		a = (a % mod) * (a % mod) % mod;
		b >>= 1;
	}
	return ans;
}
ll c(ll n, ll m){
    
    
	if(n < m) return 0;
	else return f[n] * qpow(f[n - m], mod - 2) % mod * qpow(f[m], mod - 2) % mod;
}
void fac(){
    
    
	f[0] = 1;
	for(int i = 1; i <= 2e5; i++) f[i] = f[i - 1] * i % mod; 
}


int main(){
    
    
	ios::sync_with_stdio(false);
	fac();
	cin >> t;
	while(t--){
    
    
		ll ans = 0;
		cin >> n >> m >> k;
		for(int i = 1; i <= n; i++) cin >> a[i];
		sort(a + 1, a + 1 + n);
		int l = 1;
		for(int i = 1; i <= n; i++){
    
    
			while(a[i] - a[l] > k) l++;
			ans += c(i - l, m - 1);
			ans %= mod;
		}
		cout << ans << endl;
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_42920035/article/details/111303777