2019计蒜客蓝桥杯A组模拟赛题解(Java)

本文探讨了多种算法挑战,包括求阶乘位数、炮台实验、蒜头国高速公路建设、欧拉函数计算及复杂几何问题。通过编程解决实际问题,展示了数学与算法在信息技术领域的应用。
部署运行你感兴趣的模型镜像

填空题

  1. 求阶乘位数
    这道题暴力…解决不了,可以使用通过对n!取10的对数来取n!的位数,判断对数的位数是否大于等于10000,如果是输出答案。
  • 公式
    log10(n!)=log10(1∗2∗3∗4...∗n)=log10(1)+log10(2)+...+log10(n−1)+log10(n)log10(n!)=log10(1*2*3*4...*n)=log10(1)+log10(2)+...+log10(n-1)+log10(n)log10(n!)=log10(1234...n)=log10(1)+log10(2)+...+log10(n1)+log10(n)
  • 代码
public class b1 {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		double x=0;
		for(int i=1;;i++) {
			x+=Math.log10(i);
			if(x>=10000) {
				System.out.println(i);
				break;
			}
		}
	}
}
  1. 炮台实验
    这一题让我想到了高中的组合数学问题,有n个位置,不同的位置摆放不同的数,共有n!的排列。对于留存的炮台数的期望,可以对没一个数留存下来的概率进行累加从而得到期望值。比如最大的数,无论放在哪,留存下的概率都为1。第二大的数,如果最大的数放在其前面会被摧毁,而放在后面不会被摧毁,所以留存的概率为12\frac{1}{2}21,最小的数除了放在第一个位置,其余位置都会被摧毁,所以留存的概率为1n\frac{1}{n}n1。所以要求的期望值为1+12+...+1n1+\frac{1}{2}+...+\frac{1}{n}1+21+...+n1,代入n=2019即可算出答案
  • 代码
public class b2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		double c=0;
		double n=1;
		while(n<=2019) {
			c+=1/n;
			n++;
		}
		System.out.println(c);
	}
}
  1. 蒜头国有 n 座城市,编号分别为 0,1,2,3,…,n−1。编号为 x 和 y 的两座城市之间如果要修高速公路,必须花费 x∣y 个金币,其中|表示二进制按位或。 吝啬的国王想要花最少的价格修建高速公路,使得所有城市可以通过若干条高速公路互相达到。现在请你求出 n=2019 时,一共有多少不同的方案,能让所有城市连通并且造价最低。方案数可能很大,你只需输出对 10 9 +7 取模的结果。

思路

n座城市要实现互通,并且使得造价最低,属于最小生成树问题。
最小生成树是需要在树中构造n-1条边使得n个结点都相连,不能有环。

这个问题中,可以将每个结点用二进制表示如,编号为13则二进制表示为1101。

而当把x和y这两个城市连接时要使得花费金币数最少,即使得x|y等于x自身。
如编号为1101时,与0000,0001,0100,1000,1100,1001,0101,1101相连时会使得花费的金币数为1101。

即除了x上位数为1的位置可以为1或0时才能使得x|y=x。 所以可以计算1101这个编号中1的个数为3,所以可以选择连接的城市有23−12^3-1231

而对于n个城市,每个编号可以连接的城市为其二进制编码中所含1的个数的序列排列数,所以可以编写如下代码:

package monisai1;

public class b4 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int n=2019;
		long ans=1;//0只能和自己本身相连才不会使得金币数增加
		long mod=(long)1e9+7;
		for(int i=1;i<n;i++) {
			int t=0;
			for(int j=0;i>>j>0;j++) {
				if((i>>j&1)==1) {
					t++;
					//二进制枚举, 
					//将i右移j位(且保证右移后的数大于0),将其与1按位与,结果为1则表示i对应二进制第j位上的数字为1
				}
			}
			ans=ans*((1<<t)-1)%mod; //1<<t 表示2^t 即将1左移t位
			//注意(1<<t)要哒括号 ,因为<<优先级小于-
		}
		System.out.println(ans);
	}

}

代码填空题

1. 欧拉函数

  • 公式推导
    首先先看下对12求质因子的过程,可知12=1∗2∗2∗3=22∗3112=1*2*2*3=2^2*3^112=1223=2231
    通过归纳法我们可以证明出n=p1k1∗p2k2∗...pjkjn=p_1^{k1}*p_2^{k2}*...p_j^{kj}n=p1k1p2k2...pjkj(pip_ipi为n的质因子)
    φ(n)=∏i=1jpiki\varphi(n)=\prod_{i=1}^jp_i^{ki}φ(n)=i=1jpiki
    =p1k1∗((p1−1)/p1)∗p2k2∗((p2−1)/p2)∗...pjkj∗((pj−1)/pj)=p_1^{k1}*((p_1-1)/p_1)*p_2^{k2}*((p2-1)/p2)*...p_j^{kj}*((p_j-1)/p_j)=p1k1((p11)/p1)p2k2((p21)/p2)...pjkj((pj1)/pj)
    =p1k1∗p2k2∗...pjkj∗(1−1p1)∗(1−1p2)∗...∗(1−1pj)=p_1^{k1}*p_2^{k2}*...p_j^{kj}*(1-\frac{1}{p_1})*(1-\frac{1}{p_2})*...*(1-\frac{1}{p_j})=p1k1p2k2...pjkj(1p11)(1p21)...(1pj1)
    =n∗(1−1p1)∗(1−1p2)∗...∗(1−1pj)=n*(1-\frac{1}{p_1})*(1-\frac{1}{p_2})*...*(1-\frac{1}{p_j})=n(1p11)(1p21)...(1pj1)
  • 代码
import java.util.*;

public class Main {
    public static int euler(int n) {
        int res = n;
        for (int i = 2; i <= n; i++) {
            if (n % i == 0) {
                res = res-res/i ;
                while (n % i == 0) {
                    n /= i;
                }
            }
        }
        return res;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        System.out.println(euler(n));
    }
}

程序设计

  1. 掎角之势
package monisai1;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class c1_answer {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub

		int N;
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		N=Integer.parseInt(br.readLine());
		while(N--!=0){
			StringTokenizer token=new StringTokenizer(br.readLine());
			int x1=Integer.parseInt(token.nextToken());
			int y1=Integer.parseInt(token.nextToken());
			int x2=Integer.parseInt(token.nextToken());
			int y2=Integer.parseInt(token.nextToken());
			int x3=Integer.parseInt(token.nextToken());
			int y3=Integer.parseInt(token.nextToken());
		      
			
			//假设三点为A、B、C
			x1 -= x3; 
	        y1 -= y3;
	        x2 -= x3;
	        y2 -= y3;
			//计算两条边向量AC(x1,y1)BC (x2,y2)
			if(x1*y2==x2*y1) { //叉乘公式 S=1/2*BA*BC=1/2*(x1*y2-x2*y1) 如果三角形面积为0则表明解不存在
				System.out.println("NO SOLUSTION");
				continue;
			}
			double s=Math.abs(x1*y2-x2*y1);  //三角形ABC面积的一半
			double a=Math.sqrt(x1*x1+y1*y1);
			double b=Math.sqrt(x2*x2+y2*y2);
			x1-=x2;
			y1-=y2;
			double c = Math.sqrt(x1 *x1  + y1  *y1);
			  //计算AB的距离  注意未避免c计算错误  在之前计算AC BC向量时要A,B的坐标要减去同一个点的坐标
			double r1=s/(a+b+c); //内接圆半径公式 
			double r2=a*b*c/s/2;// 外接圆半径公式
			System.out.println(String.format("%.10f", Math.acos(-1)*r1*r1)+" "+String.format("%.10f", Math.acos(-1)*r2*r2));
		}
		System.out.println(Integer.MAX_VALUE);
		System.out.println(Long.MAX_VALUE);
	}

}

  1. 轻重搭配


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

	static int []a=new int[500010];
	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		int N=Integer.parseInt(br.readLine());
		StringTokenizer token=new StringTokenizer(br.readLine());
		for(int i=0;i<N;i++) {
			a[i]=Integer.parseInt(token.nextToken());
		}
		Arrays.sort(a, 0,N);
	
		int ans=N;
		int j=N/2;
		for(int i=0;i<N/2;i++) {
			while(j<N&&a[j]<2*a[i]) j++;
			if(j==N) break;
			ans--;
			j++;
		}
		System.out.println(ans);
	}
}

贪心算法,初始票设置为n,两两配对,从数组中的0号位置开始和n/2位置后的数据开始比较,如果符合超出a[i]两倍的条件就开始配对,配对成功就将购票数减一。接着继续往下配对,直至pos到达终点。

您可能感兴趣的与本文相关的镜像

PyTorch 2.6

PyTorch 2.6

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值