2019年湘潭大学程序设计竞赛(重现赛)题解

文章目录

  • A. Who's better?(签到)
  • B. Number(签到)
  • C. Math Problem(数学)
  • D. Stone(贪心)
  • F. Black & White(双指针)


A. Who’s better?(签到)

原题链接:https://ac.nowcoder.com/acm/contest/893/A

思路:水题,直接if…else…循环求出即可。


Code(C++):

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std; 
int main(){
	ios::sync_with_stdio(0);
	int n1,p1,s1,n2,p2,s2;
	cin>>n1>>p1>>s1;
	cin>>n2>>p2>>s2;
	if(n1>n2)
		cout<<1<<endl;
	else if(n1<n2)
		cout<<2<<endl;
	else{
		if(p1<p2)
			cout<<1<<endl;
		else if(p1>p2)
			cout<<2<<endl;
		else{
			if(s1<s2)
				cout<<1<<endl;
			else if(s1>s2)
				cout<<2<<endl;
			else
				cout<<"God"<<endl;
		} 
	}
	return 0;
}

Code(Java):

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n1 = in.nextInt();
		int s1 = in.nextInt();
		int p1 = in.nextInt();
		int n2 = in.nextInt();
		int s2 = in.nextInt();
		int p2 = in.nextInt();
		if(n1>n2)
			System.out.println(1);
		else if(n1<n2)
			System.out.println(2);
		else{
			if(p1<p2)
				System.out.println(1);
			else if(p1>p2)
				System.out.println(2);
			else{
				if(s1<s2)
					System.out.println(1);
				else if(s1>s2)
					System.out.println(2);
				else
					System.out.println("God");
			} 
		}
	}

}


B. Number(签到)

原题链接:https://ac.nowcoder.com/acm/contest/893/B

思路:水题,直接模拟即可。


Code(C++):

#include <iostream>
#include <algorithm>
using namespace std;
int main(){
	ios::sync_with_stdio(0);
	int t;
	cin>>t;
	while(t--){
		int n;
		cin>>n;
		int ans=0;
		while(n>1){
			ans++;
			if(n%10==0)
				n/=10;
			else
				n+=1;
		}
		cout<<ans<<endl;
	}
	
	return 0;
}

Code(Java):

C++能过,Java超时了,证明了Java运行速度确实比C++慢了很多,不过问题不大,写Java只是为了熟悉一下Java语法。

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in = new Scanner(System.in);
		int t = in.nextInt();
		while(t-- >0) {
			int n = in.nextInt();
			int ans=0;
			while(n>1) {
				ans++;
				if(n%10==0)
					n/=10;
				else
					n+=1;
			}
			System.out.println(ans);
		}
	}
}


C. Math Problem(数学)

原题链接:https://ac.nowcoder.com/acm/contest/893/C

思路:a^3对192取模等于1,其实就是a%192 ==1。那么只要找出区间 [l,r] 中符合条件的最小数x0和最大数xn以及个数s,求等差数列之和,即 ans = (x0+x1) * s / 2。

具体数学证明 a=1+192*k(即 a % 192 = 1):
2019年湘潭大学程序设计竞赛(重现赛)题解_第1张图片

Code(C++):

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int main(){
	ios::sync_with_stdio(0);
	int t;	cin>>t;
	while(t--){
		ll l,r;
		cin>>l>>r;
		while(l%192!=1)
			l++;
		while(r%192!=1)
			r--;
		if(l>r){
			cout<<0<<endl;
		}
		else{
			int n=(r-l)/192+1;
			ll ans=(l+r)*n/2;
			cout<<ans<<endl;
		}
	}
	return 0;
}

Code(Java):注意,要全部定义为long型,否则通过不了。

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int t = in.nextInt();
		while(t-- >0) {
			long l = in.nextInt();
			long r = in.nextInt();
			while(l%192!=1)
				l++;
			while(r%192!=1)
				r--;
			if(l>r)
				System.out.println(0);
			else{
				long n = (r-l)/192+1;
				long ans = (l+r)*n/2;
				System.out.println(ans);
			}
		}
	}
}


D. Stone(贪心)

原题链接:https://ac.nowcoder.com/acm/contest/893/D

思路:合并石子堆,那么必定进行 n-1 次操作,那么要使消耗体力最小,就是石子数累加和-最大一堆的石子数。题目有个误区就是本来以为石子堆是固定位置的,不能进行排序的,但其实可以。


Code(C++):

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll a[100000];
int main(){
	ios::sync_with_stdio(0);
	int t;	cin>>t;
	while(t--){
		int n;	cin>>n;
		if(n==1){
			cout<<0<<endl;
			break;
		}
		for(int i=0;i<n;i++)
			cin>>a[i];
		sort(a,a+n);
		ll ans=0;
		for(int i=0;i<n-1;i++)
			ans+=a[i];
		cout<<ans<<endl;
	}
	return 0;
}

Code(Java):

import java.util.Arrays;
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int t = in.nextInt();
		while(t-- >0) {
			int n = in.nextInt();
			if(n==1){
				System.out.println(0);
				break;
			}
			long a[] = new long[1000000];
			for(int i=0;i<n;i++)
				a[i] = in.nextInt();
			Arrays.sort(a,0,n);
			long ans=0;
			for(int i=0;i<n-1;i++)
				ans+=a[i];
			System.out.println(ans);
		}
	}
}


F. Black & White(双指针)

原题链接:https://ac.nowcoder.com/acm/contest/893/F


思路:
这道题官方题解是前缀和+二分,但这里用的是直接双指针暴力模拟。遍历两遍,分别确定反转 ‘0’ 和反转 ‘1’ 后的最大连续 ‘1’ 和 ‘0’ 个数,最后输出最大的那个数。


Code(C++):

#include <iostream>
#include <algorithm>
using namespace std;
int main(){
	ios::sync_with_stdio(0);
	int t;	cin>>t;
	while(t--){
		int n,m;
		string s;
		cin>>n>>m>>s;
		int ans=-1,sum1=0,l=0;
		for(int r=0;r<n;r++){	//把'0'反转 
			if(s[r]=='0'){
				sum1++;
				if(sum1>m){
					while(s[l++]!='0');
					ans=max(ans,r-l+1);
				}
			}
			ans=max(ans,r-l+1);
		}
		l=0;	//把左指针重新初始化为0 
		int sum2=0;
		for(int r=0;r<n;r++){
			if(s[r]=='1'){
				sum2++;
				if(sum2>m){
					while(s[l++]!='1');
					ans=max(ans,r-l+1);
				}
			}
			ans=max(ans,r-l+1);
		}
		cout<<ans<<endl;
	}
	return 0;
}

Code(Java):

import java.util.Arrays;
import java.util.Scanner;
import java.lang.Math;
public class Main {
	static char[] s;
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		long t = in.nextInt();
		while(t-- >0) {
			int n = in.nextInt();
			int m = in.nextInt();
			in.nextLine();
			s = in.nextLine().toCharArray();
			int ans=-1,sum1=0,l=0;
			for(int r=0;r<n;r++){	//把'0'反转 
				if(s[r]=='0'){
					sum1++;
					if(sum1>m){
						while(s[l++]!='0');
						ans=Math.max(ans,r-l+1);
					}
				}
				ans=Math.max(ans,r-l+1);
			}
			l=0;	//把左指针重新初始化为0 
			int sum2=0;
			for(int r=0;r<n;r++){
				if(s[r]=='1'){
					sum2++;
					if(sum2>m){
						while(s[l++]!='1');
						ans=Math.max(ans,r-l+1);
					}
				}
				ans=Math.max(ans,r-l+1);
			}
			System.out.println(ans);
		}
	}
}



后续待更新

你可能感兴趣的:(算法)