Solution to CCPC trial of Software College

Keywords: Algorithm

preface

The problem solution is a little crude. It will be updated and optimized slowly later. Make do with it first. If you have any questions, just say them directly in the group or in the comment area.

7-1 primary school topics

For rounding, just judge the last decimal place. Examine the processing of strings. You can also use long double.
The range of n is 0 < n < = 1e18. The accuracy of the double is 2 ^ 52-1 = 4503599627370495, which is only about 15 digits, so there will be problems. The accuracy of the long double is about 19 digits, which can be passed (I wanted to card the long double, but later I thought about it...). The solution of string processing is to divide the decimal point, find the value of the number of faces, and then judge the value of one digit after the decimal point. If it is greater than or equal to 5, add one, otherwise subtract one.
string manipulation:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main(){
	string str;
	cin >> str;
	ll ans = 0, f = 0;
	while(str[f] != '.' && f<str.size()) {
		ans = ans*10 + str[f]-'0';
		f++;
	}
	f++;
	if(str[f] >= '5') ans++;
	cout << ans;
}

long double solution

#include<bits/stdc++.h>
using namespace std;
int main(){
	long double a;
	cin >> a;
	// printf is automatically rounded
	printf("%.0Lf",a);
}

7-2 Xiao Ming's work

Examine the use of selection statements, and there is no pit in the data.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main(){
	int t;
	cin >> t;
	while(t--){
		int op, a, b;
		cin >> op >> a >> b;
		if(op == 1) cout << a+b <<'\n';
		else if(op == 2) cout << a-b <<'\n';
		else if(op == 3) cout << a*b <<'\n';
		else if(op == 4) cout << a/b <<'\n';
	}
} 

7-3 Xiao Ming's wonderful dream

Examine the use of sorting functions. Adapted from the original title of provincial competition in previous years. After the cmp comparison function is written, sort the output directly.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

string str[200050];

bool cmp(string a, string b){
	reverse(a.begin(),a.end());
	reverse(b.begin(),b.end());
	string c, d;
	int f = 0;
	for(int i = 0; i<a.size(); i++){
		if(a[i] != '0') f = 1;
		if(f) c+=a[i];
	}
	f = 0;
	for(int i = 0; i<b.size(); i++){
		if(b[i] != '0') f = 1;
		if(f) d+=b[i];
	}
	if(c == d) return a.size()<b.size();
	if(c.size() == d.size())	return c < d;
	return c.size() < d.size();
}
int main() {
	int a, b, n;
	cin >> a >> b;
	n = b-a+1;
	for(int i = 0; a<=b; i++,a++){
		str[i] = to_string(a);
	} 
	sort(str,str+n, cmp);
	for(int i = 0; i<n; i++){
		if(i != 0) cout << " "; 
		cout << str[i];
	};
}


7-4 parity

Just try a few numbers and see the law. Probably
n%4 == 1 Either
n%4 == 2 Odd
n%3 == 3 Either
n%4 == 0 Even
The proof process is also very simple, omitted.

#include<bits/stdc++.h>
using namespace std;

void solve(){
	int n;
	cin >> n;
    if(n%2) cout << "Either" << endl;
    else if((n/2)%2) cout << "Odd" << endl;
    else cout << "Even" << endl;
}
int main(){
	int t;
	cin >> t;
	while(t--)	solve();
} 

7-5 minus

Maybe it's just greedy to reduce it. The title is required to start from 1. The back can only be twice as big as the front.
Then it can be reduced as before or doubled each time.
In order to minimize the number of times we reduce, we must double as much as we can.
How can we double it?
Since you have to reduce it at least after doubling, only the current value of n is a multiple of the doubled number. To double, otherwise it will be reduced all the time.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
	int n, ans = 0, f = 1;
	cin >> n;
	while(n){
		n -= f;
		ans++;
		if(n % (f*2) == 0) f = f*2;
	}
	cout << ans << '\n';
}

int main(){
	int t;
	cin >>t;
	while(t--) solve();
}

7-6 palindrome string

It is not necessary to judge whether this string is a palindrome string every time you ask. Each time you ask, only one number is changed. Therefore, you only need to remember the last state and add the modified state to judge whether it is a palindrome string.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
	string str;
	char c;
	int q, a, cnt = 0;
	cin >> str >> q;
	int n = str.size();
	for(int i = 0; i < n/2; i++){
		if(str[i] == str[n-i-1]) cnt++;
	}
	while(q--){
		cin >> a >> c;
		int f = 0;
		if(str[a-1] == str[n-a]) f = 1;
		str[a-1] = c;
		if(str[a-1] == str[n-a]){
			if(f == 0) cnt++;
		}else{
			if(f == 1) cnt--;
		}
		if(cnt == n/2) cout << "Yes\n";
		else cout << "No\n";
	}
}

7-7 candy delivery 1

Find the maximum sum and require an even number. Directly find the sum of all numbers. If the sum is even, it is the answer directly. If it is odd, subtract the smallest odd number from all numbers, and it becomes even.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main(){
	int n, a, mi = 1e9+10;
	ll sum = 0;
	cin >> n;
	for(int i = 1;  i<= n; i++){
		cin >> a;
		sum += a;
		if(a&1) mi = min(mi, a);
	}
	if(sum&1) sum -= mi;
	cout << sum;
}

7-8 candy delivery 2

One year, the original title of the Blue Bridge Cup was changed. Please see the specific solution
K-fold interval
Find the number that the sum of intervals [l,r] is a multiple of K. For interval sum, we can find it by prefix sum. We specify sum[i] to represent the sum of the first element to the i-th element. So sum[r] - sum[l-1] is the sum of interval [l,r]. The sum of interval [l,r] is a multiple of K, i.e. (sum[r] - sum[l-1])%k == 0, i.e. sum[r]%k == sum[l-1]%k

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int arr[maxn], mp[maxn];
int main(){
	ll n, k, a;
	cin >> n >> k;
	for(int i = 1; i<=n; i++){
		cin >> a;
		arr[i] = (arr[i-1]+a) % k;
		mp[arr[i]]++;
	}
	mp[0]++;
	ll ans = 0;
	for(int i = 0; i < k; i++){
		ans += 1ll*(mp[i]-1)*mp[i]/2;
	}
	cout << ans;
}

7-9 work after graduation

To give a tree with weight, you can change the position of one edge. After changing, there must be a tree. It is required that the diameter of the tree after changing is the smallest.
General idea: obviously, the edge removed from the optimal solution must be on the diameter of the original tree, otherwise the distance between the two points with the largest traffic cost will not be shortened. n is so small that you can enumerate each removed edge.
After removing one edge, the original drawing is changed into two trees. After connecting the two trees, the maximum transportation cost is
max {the diameter of the first tree, the diameter of the second tree, the distance from the "center of gravity" of the two trees to the farthest node and + the length of this edge} here, the "center of gravity" of the tree refers to a node in the tree, and the maximum distance from it to any node in the tree is the minimum
Tree diameter calculation method:
Find a random point u and find the farthest point v in the tree. Then find the farthest point w from V in the tree, and the distance from V to w is the diameter of the tree. And the solution of O(n).

#include<bits/stdc++.h>
using namespace std;

const int N=5005;
const int inf=1000000000;

int n,cnt,last[N],mn,val,mx1[N],mx2[N],bel1[N],bel2[N];
struct edge{int to,next,w;}e[N*2];

int read(){
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

void addedge(int u,int v,int w){
    e[++cnt].to=v;e[cnt].w=w;e[cnt].next=last[u];last[u]=cnt;
    e[++cnt].to=u;e[cnt].w=w;e[cnt].next=last[v];last[v]=cnt;
}

void get_dia(int x,int fa){
    mx1[x]=mx2[x]=0;
    for (int i=last[x];i;i=e[i].next){
        if (e[i].to==fa) continue;
        get_dia(e[i].to,x);
        if (mx1[e[i].to]+e[i].w>mx1[x]) mx2[x]=mx1[x],mx1[x]=mx1[e[i].to]+e[i].w;
        else if (mx1[e[i].to]+e[i].w>mx2[x]) mx2[x]=mx1[e[i].to]+e[i].w;
    }
    val=max(val,mx1[x]+mx2[x]);
}

void get_cen1(int x,int fa){
    mx1[x]=mx2[x]=0;
    for (int i=last[x];i;i=e[i].next){
        if (e[i].to==fa) continue;
        get_cen1(e[i].to,x);
        int v=mx1[e[i].to]+e[i].w,id=e[i].to;
        if (v>mx1[x]) mx2[x]=mx1[x],bel2[x]=bel1[x],mx1[x]=v,bel1[x]=id;
        else if (v>mx2[x]) mx2[x]=v,bel2[x]=id;
    }
}

void get_cen2(int x,int fa){
    mn=min(mn,mx1[x]);
    for (int i=last[x];i;i=e[i].next){
        if (e[i].to==fa) continue;
        int v,to=e[i].to;
        if (bel1[x]==e[i].to) v=mx2[x]+e[i].w;
        else v=mx1[x]+e[i].w;
        if (v>mx1[to]) mx2[to]=mx1[to],bel2[to]=bel1[to],mx1[to]=v,bel1[to]=x;
        else if (v>mx2[to]) mx2[to]=v,bel2[to]=x;
        get_cen2(e[i].to,x);
    }
}

int main(){
    n=read();
    for (int i=1;i<n;i++){
        int x=read(),y=read(),z=read();
        addedge(x,y,z);
    }
    int ans=inf;
    for (int i=1;i<n;i++){
        int x=e[i*2-1].to,y=e[i*2].to,z=e[i*2].w;
        val=0;get_dia(x,y);get_dia(y,x);
        mn=inf;get_cen1(x,y);get_cen2(x,y);
        int tmp=mn;
        mn=inf;get_cen1(y,x);get_cen2(y,x);
        val=max(val,tmp+mn+z);
        ans=min(ans,val);
    }
    printf("%d",ans);
    return 0;
}

7-10 geometry instructor

It's not difficult to ask for violence. Maybe it's because no one wrote it at the end. But for a long time, I don't know what the hell I'm writing in this code. I'll be more specific later.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1005;
double arr[N];

int main(){
	int n;
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	while(cin >> n){
		for(int i = 0; i<n; i++) cin >> arr[i];
		int f = 0;
		for(int i = 1; i < n; i++){
			double k = (1.0*arr[i]-arr[0])/(1.0*i);
			double b = 1.0*arr[0];
			map<double, int> mp; mp[b] = 1;
			for(int j = 0; j < n; j++){
				if(j == i) continue;
				mp[1.0*arr[j]-k*j] = 1;
				if(mp.size() >= 3) break;
			}
			if(mp.size() == 2){
				f = 1; break;
			} 	
		} 
		if(f == 0) 
		for(int i = 2; i < n; i++){
			double k = (1.0*arr[i]-arr[1])/(1.0*i-1);
			double b = 1.0*arr[1] - k;
			map<double, int> mp; mp[b] = 1;
			for(int j = 0; j < n; j++){
			//	if(j == i) continue;
				mp[1.0*arr[j]-k*j] = 1;
				if(mp.size() >= 3) break;
			}
			if(mp.size() == 2){
				f = 1; break;
			} 	
		} 
		if(f || n == 2) cout << "Yes" << endl;
		else cout << "No" << endl;
	}	
}

Posted by public-image on Sun, 17 Oct 2021 19:30:41 -0700