洛谷题单:入门【循环结构】

(1)P5718 【深基4.例2】找最小值
不亏是第一题,果然简洁明了。就是一个for循环,维护一个最小值。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int min=sc.nextInt();
		for(int i=1;i<n;i++) {
			min=Math.min(min,sc.nextInt());
		}
		System.out.println(min);
	}
}

(2)P5719 【深基4.例3】分类平均
循环遍历下,用几个变量存A类的总和,A类的个数,B类的总和,B类的个数。遍历后输出A总和/A个数,B总和/B个数,保留一位小数。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt(),k=sc.nextInt();
		double A_sum=0,B_sum=0;
		int A_count=0,B_count=0;
		for(int i=1;i<=n;i++) {
			if(i%k==0) {
				A_sum+=i;
				A_count++;
			}
			else {
				B_sum+=i;
				B_count++;
			}
		}
		System.out.println(String.format("%.1f", A_sum/A_count)+" "+String.format("%.1f", B_sum/B_count));
	}
}

(3)P5721 【深基4.例6】数字直角三角形
这题的题目没有说清楚,这题的意思是给出一个n,这个代表这个三角形的行数和列数,然后从1不断增加到n来填满这个三角形。但是规定数字是两位的,也就是说1要写成01的格式。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int count=1;
		for(int i=0;i<n;i++) {
			for(int j=0;j<n-i;j++) {
				System.out.print(String.format("%02d", count++));
			}
			System.out.println();
		}
	}
	
}

(4)P1009 阶乘之和
求一个数的阶乘应该是一个基本操作吧,就是用一个递归,让n*f(n-1),直到n小于1,停止递归。这里就是要用循环求多个数的阶乘。但是这道题作为一道普及难度的题,肯定是有它的道理的,因为这道题要用高精度,50!是根本存不下的,更不要说是对1-50的阶乘求和。

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		BigInteger sum=new BigInteger("0");
		for(int i=1;i<=n;i++) {
			sum=sum.add(f(i));
		}
		System.out.println(sum);
	}
	public static BigInteger f(int n) {
		if(n==1)
			return new BigInteger("1");
		return new BigInteger(n+"").multiply(new BigInteger(f(n-1)+""));
	}
}

(5)P1980 计数问题
这题问的是1-n中,数字x一共出现了几次,这里有个坑就是如果x在一个数字中多次出现,那么就要多次计数。这题标签给了高性能,但数据量也才10^6,所以就用循环扫一下就能过。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt(),x=sc.nextInt();
		int sum=0;
		for(int i=1;i<=n;i++) {
			int ii=i;
			while(ii>0) {
				if(ii%10==x) {
					sum++;
				}
				ii/=10;
			}
		}
		System.out.println(sum);
	}
}

(6)P1035 级数求和
既然它有这个当n足够大时,Sn>k这个定理。我们就不用怕,直接一个无限的循环,一只加1/i,然后i++。直到这个累加和大于k,就直接输出这个i,结束循环。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int k=sc.nextInt();
		double sum=0;
		int i=1;
		while(true) {
			sum+=1.0/i;
			if(sum>k) {
				System.out.println(i);
				return;
			}
			i++;
		}
	}
}

(7)P2669 金币
一道模拟题目,这里要建立几个变量,分别存储,获得的金币总数,当前天数应该获得的金币数,在获得这个金币数的天数还剩几天。当剩0天的时候,让当前应该获得的金币数加1.

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int sum=0,num=1,day=1;
		for(int i=1;i<=n;i++) {
			if(day==0) {
				day=num+1;
				num++;
			}
			sum+=num;
			day--;
		}
		System.out.println(sum);
	}
}

(8)P5722 【深基4.例11】数列求和
这题有意思,居然不能直接使用等差数列的公式,不过一样的,反正是电脑算,用个循环累加一下就出来了。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt(),sum=0;
		for(int i=1;i<=n;i++) {
			sum+=i;
		}
		System.out.println(sum);
	}
}

(9)P5723 【深基4.例13】质数口袋
这题是一道考素数的题目,这里它的数据范围很小,所以我们用最普通的求素数的方法即可,时间复杂度O(NlogN)。循环判断每一个数是不是素数,如果是素数的花累加都口袋里,当口袋装不下了就结束循环。我这里用一个集合来当口袋,最后输出集合中元素和集合的大小即可。

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		ArrayList<Integer> a=new ArrayList<Integer>();
		int sum=0;
		for(int i=2;i<=100000;i++) {
			if(prime(i)) {
				if(sum+i>n) {
					break;
				}
				sum+=i;
				a.add(i);
			}
		}
		for(int x:a) {
			System.out.println(x);
		}
		System.out.println(a.size());
	}
	public static boolean prime(int n) {
		for(int i=2;i*i<=n;i++) {
			if(n%i==0) {
				return false;
			}
		}
		return true;
	}
}

这题如果数据量再大一点,这种时间复杂度的算法就不太够用了,就要用素数筛法,埃式筛法是一种O(NloglogN)时间复杂度的筛法,虽然这题可以不用,但是当作一道练手的题目也未尝不可。另外,再补充一下,还有一种更快的筛法,欧拉筛。时间复杂度O(N),感兴趣可以去网上百度下,当作一个模板背下来。


import java.util.ArrayList;
import java.util.Scanner;

public class Main {
	static int n;
	static boolean[] vis;
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		vis=new boolean[n+1];
		prime();
		for(int x:a) {
			System.out.println(x);
		}
		System.out.println(a.size());
	}
	static ArrayList<Integer> a=new ArrayList<Integer>();
	public static void prime() {
		vis[0]=vis[1]=true;
		for(int i=2;i<=n;i++) {
			if(i*i>n) {
				break;
			}
			if(!vis[i]) {
				for(int j=i*i;j<=n;j+=i) {
					vis[j]=true;
				}
			}
		}
		int sum=0;
		for(int i=2;i<=n;i++) {
			if(!vis[i]) {
				if(sum+i>n) {
					break;
				}
				sum+=i;
				a.add(i);
			}
		}
		
	}
}

(10)P1217 [USACO1.5]回文质数 Prime Palindromes
这道题其实题目本身并不难,无非是写一个判断回文数的函数,再写一个判断是不是质数的函数,然后再循环扫一下就行。但这道题这么做肯定不行,因为数据规模是一亿,这样做肯定超时。所以我们要寻找一些规律来缩小我们搜索的范围。下面是找规律:
一位数:全是回文数,质数有1,3,5,7。所以回文质数有1,3,5,7
二位数:回文数有11,22,33…但是他们都是11的倍数,所以回文质数只有11
三位数:这道题的提示告诉我们,只有首位是奇数才会是回文数,所以
这样枚举101,303,505…
四位数:同样首位是奇数 1001,3003,但是我们发现,所有4位数的回文数都是11的倍数,也就是说不可能是质数。那么所有4位数都不用枚举。
同理,6位数和8位数也是这样,直接不用枚举。
这样我们就把数据规模缩小了一大半,接下来就是循环遍历了。

import java.util.Scanner;

public class Main {
	static int[] a=new int[100000];
	public static boolean prime(int n) {
		for(int i=2;i*i<=n;i++) {
			if(n%i==0) {
				return false;
			}
		}
		return true;
	}
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int x=sc.nextInt(),y=sc.nextInt();
		int p=0;
		for(int i=2;i<10;i++) {  //一位数
			if(prime(i)) {
				a[p++]=i;
			}
		}
		a[p++]=11;   //两位数
		for(int i=1;i<10;i+=2) {  //三位数
			for(int j=0;j<10;j++) {
				if(prime(i*101+j*10)) {
					a[p++]=i*101+j*10;
				}
			}
		}
		for(int i=1;i<10;i+=2) {  //五位数
			for(int j=0;j<10;j++) {
				for(int k=0;k<10;k++) {
					if(prime(i*10001+j*1010+k*100)) {
						a[p++]=i*10001+j*1010+k*100;
					}
				}
			}
		}
		for(int i=1;i<10;i+=2) {  //五位数
			for(int j=0;j<10;j++) {
				for(int k=0;k<10;k++) {
					for(int l=0;l<10;l++) {
						if(prime(i*1000001+j*100010+k*10100+l*1000)) {
							a[p++]=i*1000001+j*100010+k*10100+l*1000;
						}
					}
				}
			}
		}
		for(int i=0;i<p;i++) {
			if(x<=a[i]&&a[i]<=y) {
				System.out.println(a[i]);
			}
		}
	}
}

(11)P1423 小玉在游泳
这题和级数求和那题是一样的,定义一个无限循环,每次累加游泳的长度,直到它游泳游到了规定的长度,退出循环。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		double n=sc.nextDouble();
		int count=0;
		double speed=2;
		double sum=0;
		while(true) {
			count++;
			sum+=speed;
			speed*=0.98;
			if(sum>=n) {
				break;
			}
		}
		System.out.println(count);
	}
}

(12)P1307 数字反转
数字反转自然也可以当作字符串反转处理,就是要判断一下前导0和负数的情况。但是更简洁的方法自然是循环去取模,然后累加乘10倍。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int sum=0;
		while(n!=0) {
			sum=sum*10+n%10;
			n/=10;
		}
		System.out.println(sum);
	}
}

(13)P1720 月落乌啼算钱
这道题的题目描述都是什么乱七八糟的,不是直接代入n进公式出结果的好啦嘛。一行代码就解决了呀。有题解说这是斐波拉契数列,但能一行解决的问题咱们就不搞这些花里胡哨的。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		System.out.println(String.format("%.2f",(Math.pow((1+Math.sqrt(5))/2,n)-Math.pow((1-Math.sqrt(5))/2,n))/Math.sqrt(5)));
	}
}

(14)P5724 【深基4.习5】求极差
这道题和第一题好像,只是它现在不只是求个最小值了,还要求个最大值,然后一减就是答案。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int min=1000;
		int max=0;
		for(int i=0;i<n;i++) {
			int x=sc.nextInt();
			min=Math.min(min, x);
			max=Math.max(max, x);
		}
		System.out.println(max-min);
	}
}

(15)P1420 最长连号
设置一个变量存储最长的连号。扫描一遍这些数字,设置一个变量记录当前的连号长度,如果碰到中断的情况,和最长的连号那个变量比较,如果这个变量更大则替换掉那个最长的连号,然后把这个变量置为1。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int max=0;
		int last=sc.nextInt();
		int temp=1;
		for(int i=1;i<n;i++) {
			int x=sc.nextInt();
			if(x==last+1) {
				temp++;
			}
			else {
				max=Math.max(temp, max);
				temp=1;
			}
			last=x;
		}
		System.out.println(max);
	}
}

(16)P1075 质因数分解
有一点数学的味道。既然他说了这个输入的正整数能被分解成两个质数的乘积,那么我们求出小的那个就可以反推出大的那个。这里我们不用判断质数,因为根据唯一分解定理,一个数只能被分解成一组质数,而这道题又说了可以被分解成两个质数,那么不可能有小于这个数的合数能被这个数整除。我们可以反证一下,如果有小于n的一个合数能被n整除,那么这个合数能分解成两个更小的质数。而通过题目我们知道,只有一组质数乘积的解会等于n,所以如果有合数的话就说明不止一组解,与题目矛盾。这题虽然数学要推一下,但是代码很简单。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		for(int i=2;i<=n;i++) {
			if(n%i==0) {
				System.out.println(n/i);
				return;
			}
		}
	}
}

(17)P4956 [COCI2017-2018#6] Davor
这题,首先得出一个题目写出一个二元一次方程。364x+1092k=n
那么,我们两个循环遍历找到这个等式成立的值即可,因为x要尽可能大,k尽可能小,所以x要从大的开始遍历,k从小的开始遍历.

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		for(int x=100;x>=0;x--) {
			for(int k=1;k<1000;k++) {
				if(364*x+1092*k==n) {
					System.out.println(x);
					System.out.println(k);
					return;
				}
			}
		}
	}
}


(18)P1089 津津的储蓄计划
一道模拟题。建立一个变量储存妈妈那里的钱数,再建立一个变量储存自己手上的钱数,然后循环12次,每个月处自己的钱加300,然后减去开支,把多的钱大于100的部分给妈妈。最后输出自己的钱加上妈妈的钱乘1.2.循环的时候特判下钱不够花的情况,直接把月份输出,终止循环。

import java.util.Scanner;

public class Main{
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int[] arr=new int[12];
		for(int i=0;i<12;i++) {
			arr[i]=sc.nextInt();
		}
		int sum=0;
		int now=0;
		for(int i=0;i<12;i++) {
			now+=300;
			if(now<arr[i]) {
				System.out.println(-i-1);
				return;
			}
			now-=arr[i];
			sum+=now/100*100;
			now-=now/100*100;
		}
		System.out.println((int)(sum*1.2+now));
	}
}

发布了13 篇原创文章 · 获赞 15 · 访问量 3423

猜你喜欢

转载自blog.csdn.net/qq_43751506/article/details/104873260
今日推荐