1 、 购物单:
题目分析+代码
评测标准答案: 5200
方法1: 在excel中计算,复制粘贴后对数据进行以空格为标志分列,删除汉字,用公式计算。
方法2: 用计算机自带的计算器计算。
方法3: 将购物单复制到代码中,把**** 替换成`+`号,去掉汉字`折`,改为两位数
即9折改成90,在数字间加上 `*`,计算结果除以100即可,此方法不至于输入错误。
public class Main001{
public static void main(String[] args) {
// TODO Auto-generated method stub
double ans = 180.90 * 88
+ 10.25 * 65
+ 56.14 * 90
+ 104.65 * 90
+ 100.30 * 88
+ 297.15 * 50
+ 26.75 * 65
+ 130.62 * 50
+ 240.28 * 58
+ 270.62 * 80
+ 115.87 * 88
+ 247.34 * 95
+ 73.21 * 90
+ 101.00 * 50
+ 79.54 * 50
+ 278.44 * 70
+ 199.26 * 50
+ 12.97 * 90
+ 166.30 * 78
+ 125.50 * 58
+ 84.98 * 90
+ 113.35 * 68
+ 166.57 * 50
+ 42.56 * 90
+ 81.90 * 95
+ 131.78 * 80
+ 255.89 * 78
+ 109.17 * 90
+ 146.69 * 68
+ 139.33 * 65
+ 141.16 * 78
+ 154.74 * 80
+ 59.42 * 80
+ 85.44 * 68
+ 293.70 * 88
+ 261.79 * 65
+ 11.30 * 88
+ 268.27 * 58
+ 128.29 * 88
+ 251.03 * 80
+ 208.39 * 75
+ 128.88 * 75
+ 62.06 * 90
+ 225.87 * 75
+ 12.89 * 75
+ 34.28 * 75
+ 62.16 * 58
+ 129.12 * 50
+ 218.37 * 50
+ 289.69 * 80;
System.out.println(ans/100);
}
}
2 、纸牌三角形:
题目分析+代码
评测标准答案: 144
对1~9的数字进行全排列,然后
if(a[0]+a[1]+a[3]+a[5] = a[0]+a[2]+a[4]+a[8]
&& a[0]+a[2]+a[4]+a[8]= a[5]+a[6]+a[7]+a[8])
count++;
因为旋转、镜像后相同的视为同一种,answer = count/6;
public class Main002{
static int [] a = new int[] {1,2,3,4,5,6,7,8,9};
static int count = 0;
public static void f(int k) {
if(k==9) {
// 判断三边之和是否相等,若相等 count++;
int x1 = a[0]+a[1]+a[3]+a[5];
int x2 = a[0]+a[2]+a[4]+a[8];
int x3 = a[5]+a[6]+a[7]+a[8];
if(x1==x2 && x2 ==x3) count++;
}
/* 对 1~9 进行全排列,
* 把第 k 位以后的每一位交换到第一位
递归+回溯 */
for(int i=k;i<9;i++) {
int t = a[k];
a[k] = a[i];
a[i] = t;
f(k+1);
t= a[k];
a[k] = a[i];
a[i] = t;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
f(0);
System.out.println(count/6);
}
}
3 、承压计算:
题目分析+代码
评测标准答案:72665192664
方法一:
1.注意物品的单位和电子称的单位不同
2.数字 29行*29列,开30行30列数组,以便保存最终数据
2.构造二维数组 将数据存入二维数组。双层循环,内循环的循环次数依次增大,
读入数据(直接粘贴29行即可),读入多个空格作为分隔符。
3.更新每一行数组,a[i+1][j] +=a[i][j]/2 ; a[i+1][j+1] += a[i][j]/2;
每一个数据均分给 正下方和右下方的元素。
4.数组最后一行,为称的示数。进行排序。
5.题目给出的最小示数/求得的最小示数 = 单位的倍数
求得的最大示数 * 单位的倍数 = answer;
6. 涉及到除法,可能会出现小数,so用double数据类型
方法二: 先扩大2的30次方倍,再同理计算。
import java.util.Arrays;
import java.util.Scanner;
public class Main003{
static double[][] a = new double[30][30];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
for(int i=0;i<29;i++)
for(int j=0;j<=i;j++)
a[i][j]=in.nextDouble();
for(int i=0;i<29;i++)
for(int j=0;j<=i;j++){
a[i+1][j] +=a[i][j]/2 ;
a[i+1][j+1] += a[i][j]/2;
}
Arrays.sort(a[29]);
double answer = a[29][29]*(2086458231/a[29][0]);
System.out.println((long)answer);
}
}
4、魔方状态
评测标准答案:229878
" emmmmmm 这道题我放弃了!不会写。"
5、取数位(代码填空)
评测标准答案:f(x/10, k)
import java.util.*;
public class Main005{
static int len(int x){
if(x<10) return 1;
return len(x/10)+1;
}
// 取x的第k位数字
static int f(int x, int k){
if(len(x)-k==0) return x%10;
return f(x/10, k) ; //填空
}
public static void main(String[] args){
int x = 23513;
//System.out.println(len(x));
System.out.println(f(x,3));
}
}
6、最大公共子串(代码填空)
评测标准答案:a[i-1][j-1]+1
public class Main{
static int f(String s1, String s2){
char[] c1 = s1.toCharArray( );
char[] c2 = s2.toCharArray( );
int[][] a = new int[c1.length+1][c2.length+1];
int max = 0;
for(int i=1; i<a.length; i++){
for(int j=1; j<a[i].length; j++){
if(c1[i-1]==c2[j-1]) {
a[i][j] = a[i-1][j-1]+1; //填空
if(a[i][j] > max) max = a[i][j];
}
}
}
return max;
}
public static void main(String[] args){
int n = f("abcdkkk", "baabcdadabc");
System.out.println(n);
}
}
7 、 日期问题
题目分析+代码
1.获取 year、moth、day三个数据
2.写一个读入数据,并判断日期是否合理的方法
3.注意判断是否为闰年
4.调用方法时,传入三种不同顺序的参数
5.生成字符串时,注意小于10的月份和天数前加上0
6.用TreeSet存储字符串,以达到去重和按字典序排序的效果
import java.Util.*;
public class Main{
static Set<String> set = new TreeSet<String>();
public static boolean isLeapYear(int year){
return year%400==0 || ( year%4==0 && year%100 !=0 );
}
public static void check(int a,int b , int c){
if(a>=60 && a<=99) a += 1900;
else if(a>=0 && a<=59) a += 2000;
else return;
if(b>12||b<=0) return;
if(c>31||b<=0) return;
switch (b) {
case 4:
case 6:
case 9:
case 11:
if(c>30) return ;
break;
case 2:
if(isLeapYear(a)) {
if(c>29) return;
}else {
if(c>28) return;
}
}
set.add(a+"-"+(b<10?"0"+b:b)+"-"+(c<10?"0"+c:c));
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
String s = in.next();
int a = (s.charAt(0)-'0')*10+s.charAt(1)-'0';
int b = (s.charAt(3)-'0')*10+s.charAt(4)-'0';
int c = (s.charAt(6)-'0')*10+s.charAt(7)-'0';
check(a, b, c);
check(c, a, b);
check(c, b, a);
for(String str:set) {
System.out.println(str);
}
}
}
8 、 包子凑数
题目分析+代码
1.由扩展欧几里算法
ax + by + cz = m ; 当m不是gcd(a,b,c)的倍数时,无解。
<"对本题而言:若输入的数不互质,则凑不出的数有无数个">
2.对任何整数 a,b 和他们的最大公约数d,关于未知数 x和 y的线性丢番图方程(称为裴蜀等式):
ax + by = m 有整数解时,当且仅当m是d的倍数。
3. 裴蜀等式 有解时必然有无穷多个整数解,每组解x,y都称为裴蜀数
4. 当最大公约数为1时,即互质
如果 某个数能凑出,那么它加上任意一个输入的包子数,都能凑出
so,从零到10000扫描n次 ,逐个检查是否能凑出
import java.util.Scanner;
public class Main{
// 计算两个数的最大公约数
static int gcd1 (int a,int b){
return b==0?a:gcd1(b,a%b);
}
// 计算多个数的最大公约数
static int gcd2(int [] a){
int n = a.length;
int L = a[0];
for(int i=1;i<n;i++)
L = gcd1(L,a[i]);
return L;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int [] a = new int[n];
boolean []b = new boolean [10000];
b[0] = true;
for(int i=0;i<n;i++) {
a[i]=in.nextInt();
}
int gcd = gcd2(a);
/* 如果最大公约数不为1,一定有无数个数凑不出来
* 例如 , 多个数的最大公约数为2 ,则所以的 奇数都凑不出
*/
if(gcd!=1) {
System.out.println("INF");
System.exit(0); // 输出"INF"终止程序
}else {
/* 当最大公约数为1时,即互质
* 如果 某个数能凑出,那么它加上任意一个输入的包子数,都能凑出
so,从零到10000扫描n次 ,逐个检查是否能凑出 */
for(int i = 0;i<n;i++) {
for(int j=0;j+a[i]<10000;j++) {
if(b[j]) b[j+a[i]] = true;
}
}
}
int count = 0; //计数,记录凑不出的数
for(int i=0;i<10000;i++) {
if(b[i]==false) count++;
}
System.out.println(count);
}
}
9 、 分巧克力
题目分析+代码
1.如果单独的使用逐个循环暴力,必超时
2.使用二分法降低复杂度 直到 l=r=mid ,得出最终结果
import java.util.Scanner;
public class Main009_分巧克力 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int k = in.nextInt();
int []h = new int[n];
int []w = new int[n];
for(int i=0;i<n;i++) {
h[i]=in.nextInt();
w[i]=in.nextInt();
}
int l = 1,r=100001,ans=0;
while(l<=r) {
int count=0;
int mid=(l+r)/2;
for(int i=0;i<n;i++) {
count += (h[i]/mid)*(w[i]/mid);
}
if(count>=k) {
l=mid+1;
ans = mid;
}else {
r=mid-1;
}
}
System.out.println(ans);
}
}
10 、 K倍区间
题目分析+代码
1.对于本题评测标准共7个测试用例,前两个数据个数为100,余数9个,
后5个为100000,余数成倍增加
虽然本题的时间限制是2秒,但也要进行优化。
方法:前缀和+取模+组合数学
1. a数组存储数据,dp数组为前缀和取模后的数组
2. 前缀和数组,即dp的某项元素 为a数组相应位置及之前数组元素之和。
3. dp数组,为取模后的数组。例:输入 n=5,k=2; a={1,2,3,4,5},前缀和={1,3,6,10,15};
引入前缀和的原因: 前缀和的任意两项相减都为 数组a的一个连续区间和,可简便计算。
4. 取模后 dp={1,1,0,0,1} 任意两项相减为0,那么该区间必能整除k; 所以任意余数相等的元素必能凉凉组合。
5. 不要忽略了,单独的一个元素,也可作为子区间。所以最后应加上,余数为0的元素个数。
6. ans+=count[dp[i]]++; 此行代表每增加一个新的余数,
都能和之前已有的相同余数形成区间,所以ans加上之前已有的该余数的个数(不包括本次)
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int k = in.nextInt();
int[]a = new int[n];
int[]dp = new int[n];
int[]count = new int[k];
int last = 0;
long ans = 0;
for(int i=0;i<n;i++) {
a[i]=in.nextInt();
dp[i] = (last+a[i])%k;
last = dp[i];
ans+=count[dp[i]]++;
}
// for(int i=0;i<k;i++) {
// ans += count[i]*(count[i]-1)/2;
// }
System.out.println(ans+count[0]);
}
}