CF思维题

A.Almost Rectangle

原题链接

思路:题目大概意思是在二维矩阵里给出你两个点,有可能在同一行同一列,然后让你枚举出另外两个点,使他们成为一个矩形。这里除了需要特判的同一行同一列,要考虑边界情况外,其余都是 ch[x1][y2],ch[x2][y1]

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		while(t-->0) {
			int n = sc.nextInt();
			sc.nextLine();
			char ch[][] = new char[n][n];
			boolean flag = false;
			int x1=0,x2=0,y1=0,y2=0;
			for(int i=0;i<n;i++) {
				ch[i] = sc.nextLine().toCharArray();
			}
			for(int i=0;i<n;i++) {
				for(int j=0;j<n;j++) {
					if(!flag&&ch[i][j]=='*') {
						x1 = i;y1 = j;
						flag = true;
					}
					if(flag&&ch[i][j]=='*') {
						x2 = i;y2 = j;
					}
				}
			}
			if(x1==x2) {
				ch[x1==n-1?n-2:x1+1][y1] = '*';
				ch[x2==n-1?n-2:x2+1][y2] = '*';
			}else if(y1==y2) {
				ch[x1][y1==n-1?n-2:y1+1] = '*';
				ch[x2][y2==n-1?n-2:y1+1] = '*';
			}else {
				ch[x2][y1]='*';
				ch[x1][y2]='*';
			}
			for(int i=0;i<n;i++) {
				for(int j=0;j<n;j++) {
					System.out.print(ch[i][j]);
				}System.out.println();
			}
		}
	}
}

B.A-B Palindrome

原题链接

这题我将近写了90行,就是模拟,需要特殊考虑将序列变为对称后,“?”的个数是奇数的情况

import java.util.Scanner;
public class Main{

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		while(t-->0) {
			int a = sc.nextInt();
			int b = sc.nextInt();
			sc.nextLine();
			char arr[] = sc.nextLine().toCharArray();
			if(a+b!=arr.length) {
				System.out.println(-1);
				continue;
			}
			int index =0;
			int n = arr.length;
			for(int i=0;i<arr.length;i++) {
				if(arr[i]=='?') index++;	//记录?个数
				if(arr[i]=='0')a--;
				if(arr[i]=='1')b--;
			}
			for(int i=0;i<n;i++) {
				if(arr[i]!='?'&&arr[n-i-1]=='?') {
					if(arr[i]=='0') {
						arr[n-i-1]='0';a--;index--;
					}
					if(arr[i]=='1') {
						arr[n-i-1]='1';b--;index--;
					}
				}
				if(arr[i]=='?'&&arr[n-i-1]!='?') {
					if(arr[n-i-1]=='0') {
						arr[i]='0';a--;index--;
					}
					if(arr[n-i-1]=='1') {
						arr[i]='1';b--;index--;
					}
				}
			}
			if(index%2==0&&a%2!=0&&b%2!=0) {
				System.out.println(-1);
				continue;
			}else {
				if(index%2!=0) {
					arr[n/2]=a%2!=0?'0':'1';
					if(a%2!=0)a--;else b--;
					index--;
				}
					for(int i=0;i<n&&a>0;i++) {
						if(arr[i]=='?') {
							arr[i]='0';
							arr[n-i-1]='0';
							a-=2;
						}
					}
					for(int i=0;i<n&&b>0;i++) {
						if(arr[i]=='?'){
							arr[i]='1';
							arr[n-i-1]='1';
							b-=2;
						}
					}
			}
			boolean flag = false;
			for(int i=0;i<n;i++) {
				if(arr[i]!=arr[n-i-1]) {
					flag = true;
					System.out.println(-1);
					break;
				}
			}
			if(!flag&&(a<0||b<0)) {
				System.out.println(-1);
				flag = true;
				continue;
			}
			if(!flag) {
				for(int i=0;i<arr.length;i++) {
					System.out.print(arr[i]);
				}
				if(t!=0)System.out.println();
			}
		}
	}
}

C.Corrupted Array

原题链接

满足条件的可以分为3中情况
1.前n项和Sn=b[n]
2.前n项和Sn=b[n+1]
3.前n+1项和Sn+1-a[i]=b[n+1]这里的a[i]要通过遍历得出

import java.util.Arrays;
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		while(t-->0) {
			int n = sc.nextInt();
			Long b[] = new Long[n+2];
			long s1 = 0;//前n项和
			for(int i=0;i<n+2;i++) {
				b[i] = sc.nextLong();
			}
			Arrays.sort(b);
			for(int i=0;i<n;i++) {
				s1+=b[i];
			}
			if(s1==b[n]||s1==b[n+1]) {
				System.out.print(b[0]);
				for(int i=1;i<n;i++) {
					System.out.print(" "+b[i]);
				}
				System.out.println();
			}else {
				s1+=b[n];
				int index=n;
				for(int i=0;i<=n;i++) {
					if(s1-b[i]==b[n+1]) {
						index = i;
					}
				}
				if(index==n)System.out.println(-1);
				else {
					for(int i=0;i<n;i++) {
						if(i!=index) {
							System.out.print(b[i]+" ");
						}
					}
					System.out.print(b[n]);
					System.out.println();
				}
			}
		}
	}
}

D.Double-ended Strings

原题链接

这道题使求最大连续公共子序列,假设最大连续公共子序列长度为x,则答案为(a.length()+b.length())-max*2

import java.util.Scanner;
public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		sc.nextLine();
		while(n-->0) {
			String a = sc.nextLine();
			String b = sc.nextLine();
			if(a.length()<b.length()) {
				String t = a;
				a = b;
				b = t;
			}
			int max = Integer.MIN_VALUE;
			for(int i=0;i<a.length();i++) {
				for(int j=0;j<b.length();j++) {
					int k = 0;
					while(i+k<a.length()&&j+k<b.length()&&a.charAt(i+k)==b.charAt(j+k)) {
						k++;
					}
					max = Math.max(max,k);
				}
			}
			System.out.println((a.length()+b.length())-max*2);
		}
	}
}

E.Binary Removals

原题链接

这个我没过

F.Spy Detected!

原题链接

一个序列中只有一个数的与其他数不同,我用的是sort排序,不是在开头就是在结尾

import java.util.Arrays;
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		while(t-->0) {
			int n = sc.nextInt();
			int arr[] = new int[n];
			int b[] = new int[n];
			for(int i=0;i<n;i++) {
				arr[i] = sc.nextInt();
			}
			b=arr.clone();
			Arrays.sort(b);
			int x;	
			if(b[0]==b[1])x=b[n-1];
			else x=b[0];
			for(int i=0;i<arr.length;i++) {
				if(arr[i]==x) {
					System.out.println(i+1);
					break;
				}
			}
		}
	}
}

G.The Great Hero

这个emm没写出来

原题链接

H.Ping-pong

这一道题分析一下即可,题目中说,他们为了使自己得分最大化,都会采用最佳策略,分析可知,Alice先发球,如果Bob不接,Alice赢,接下来Alice还会发球,等Alice最后一次发球时,Bob开始反击。接下来Bob还剩余几个耐力就可以赢一场,这样来说两者的胜场都是最大的。

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		while(n-->0) {
			int x = sc.nextInt();
			int y = sc.nextInt();
			System.out.println(x-1+" "+y);
		}
		
	}
}

I.Increase and Copy

大意:初始给你一个元素 1,每次操作你可以选择让一个元素 +1 或者复制出元素.求最少需要多少次操作使其总和不小于 n .

思路:因为不用考虑恰好到达n,所以最后一步用复制肯定是最快的。
1.假如 n \sqrt{n} n 刚好是整数,那么复制 n \sqrt{n} n 肯定是最优的
2.假如 n \sqrt{n} n 不是整数,那么如果 n \sqrt{n} n * n + 1 \sqrt{n+1} n+1 >=n,如果这个满足,就用这个式子。

3.如果 n \sqrt{n} n * n + 1 \sqrt{n+1} n+1 <n,那么只能用 n + 1 \sqrt{n+1} n+1 n + 1 \sqrt{n+1} n+1

接下来还要考虑一个东西,那就是分解完第一步,剩下的是加最优呢,还是复制与加一起用最优呢?
1.如果用加得到,那么只需要加大概 n \sqrt{n} n 次即可
2.如果用复制得到,则远远大于 n \sqrt{n} n
举个例子;比如n=169*169,通过上述可知先得到169然后再复制168次即可。

如果只用加法,那么需要进行169-1次 。(总共168+168次)
如果加法复制都用,先用加法得到一个13,进行了12次。接下来13要经过12次复制,得到169.接下来,169要进行复制,但是这个169是由13个13组成的,也就是要将13个13复制168次,也就是13169次。(共12+13+13169)。所以复制一次就是最优的选择。

原题链接

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t = sc.nextInt();
		while(t-->0) {
			int n = sc.nextInt();
			int m = (int)Math.sqrt(n);
			if(m*m==n)System.out.println(m-1+m-1);
			else {
				if(m*(m+1)>=n) {
					System.out.println(m-1+m);
				}else {
					System.out.println(m+m);
				}
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值