【题解】计蒜客 2020 蓝桥杯大学 B 组省赛模拟赛(一)



A. 结果填空:有趣的数字(签到)

原题链接:https://nanti.jisuanke.com/t/43115

  • 思路: 签到题,直接暴力循环并判断每个数是否既为质数又含有5。

Code:

import java.util.*;
import java.math.*;
public class Main{
	static boolean isprime(int n) {
		if(n==1 || n==0)	return false;
		for(int i=2;i*i<=n;i++) {
			if(n%i==0)
				return false;
		}
		return true;
	}
	static boolean check(int n) {
		while(n>0) {
			if(n%10==5)	return true;
			n/=10;
		}
		return false;
	}
    public static void main(String[] args){
    	int ans=0;
        for(int i=1;i<=100000;i++) {
        	if(isprime(i) && check(i))
        		ans++;
        }
        System.out.println(ans);
    }
}


B. 结果填空:爬楼梯(dp)

原题链接:https://nanti.jisuanke.com/t/43116

  • 思路: 简单 dp

Code:

import java.util.*;
import java.math.*;
public class Main{
	static int[] dp = new int[15];
    public static void main(String[] args){
    	dp[0]=1;	dp[1]=1;	
    	dp[2]=2;	dp[3]=4;
    	for(int i=4;i<=10;i++) {
			if(i==5 || i==7)	continue;
			dp[i]=dp[i]+dp[i-1]+dp[i-2]+dp[i-3]+dp[i-4];
    	}
    	System.out.println(dp[10]);
    }
}


C. 结果填空:七巧板(数论)

原题链接:https://nanti.jisuanke.com/t/43117

  • 思路: 第一条直线最多可以划分出 6 个区域,以后每次划分比上次多划分一个区域出来,即 f[i] = f[i-1] + 1,故答案是47。

Code:

import java.util.*;
import java.math.*;
public class Main{
	static int[] f = new int[10];
    public static void main(String[] args){
    	int ans=7;
    	f[1]=6;
    	ans+=f[1];
    	for(int i=2;i<=5;i++) {
    		f[i]=f[i-1]+1;
    		ans+=f[i];
    	}
    	System.out.println(ans);
    }
}


D. 结果填空:苹果(贪心)

原题链接:https://nanti.jisuanke.com/t/43118

  • 思路: 有三种方法,分别是先取连续的三个 1,再取一个的 3 ;先取一个的 3 ,再取连续的三个 1;从左到右推过去,能取一个的 3 的就取,取完后再用后面两个篮子来凑连续的三个 1 ,答案分别是 58,57,62,故取最大的。下面只给出了第三种方案的代码。

Code:

import java.util.*;
import java.math.*;
public class Main{
	static int[] a = new int[35];
    public static void main(String[] args){
    	Scanner cin = new Scanner(System.in);
    	int ans=0;
    	for(int i=1;i<=30;i++) 
    		a[i]=cin.nextInt();
    	for(int i=1;i<=30;i++) {
    		ans+=a[i]/3;
    		a[i]%=3;
    		while(a[i]>0 && a[i+1]>0 && a[i+2]>0) {
    			ans++;
    			a[i]--;a[i+1]--;a[i+2]--;
    		}
    	}
    	System.out.println(ans);
    }
}


F. 程序设计:寻找重复项(HashMap)

原题链接:https://nanti.jisuanke.com/t/43120

  • 思路: 这道题一开始直接模拟然后用数组标记一出现过的数值,但是只过了 6 个样例,因为数组一般只能定义到 1e7 的范围。所以用 HashMap 就不怕内存会超了。如果是用 C++ 的话,就得用 unorder_map ,不然 AC 不了。还有 记得全部用 long 型,否则还是过不了一些样例。
    -感觉蓝桥杯好坑,又不能评测,又要在一次测试样例设坑!!!

Code:

import java.util.Scanner;
import java.util.HashMap;
public class Main{
	static long[] f = new long[2000100];
    public static void main(String[] args){
    	Scanner cin = new Scanner(System.in);
    	HashMap<Long,Long> mp = new HashMap<Long,Long>();
    	long a = cin.nextLong(), b = cin.nextLong(), c = cin.nextLong();
    	f[0] = 1;
    	mp.put(f[0],(long)1);
    	for(int i=1;i<=2000000;i++) {
    		f[i] = (f[i-1]*a+f[i-1]%b)%c;
    		if(mp.get(f[i])!=null) {
    			System.out.println(i);
    			return;
    		}else	mp.put(f[i], (long)1);
    	}
    	System.out.println(-1);
    }
}


G. 程序设计:被袭击的村庄(模拟)

原题链接:https://nanti.jisuanke.com/t/43121

  • 思路: 这是一道差点要了我的命的模拟题。
  1. 首先答案应该弄错了,这个出题人确实该喷,这套题已经好多道题目答案弄错了(C、D题比赛时的答案错的,已经改了,而这道答案错了,至今还没改)。输出的应该是道路、房屋、田地耐久度分别为 0 的数目,以及整个村庄受到的总伤害。而不是输出道路、房屋、田地分别受到的伤害以及村庄受到的总伤害。
  2. 直接模拟,要注意的就是炸弹伤害那里的循环变量,要定义两个新的变量来表示炸弹范围里的坐标,而不是直接用地图的坐标。
  3. 最后,一开始因为有个细节写错了,导致改了很久,找不出bug(哭了)。但是数据很水,这个错误后来没改过来居然还给我过了。
  4. 直接用 C++ 吧,我累了,不想要再写一遍 Java 了。

Code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=0x3f3f3f3f;
const int pi=acos(-1.0);
const int mod=1e9+7;
int v[550][550],maps[550][550],life[550][550];
ll sum=0,d_sum=0,f_sum=0,t_sum=0;
int dx[8]={-1,-1,-1,0,0,1,1,1},dy[8]={1,0,-1,1,-1,1,0,-1};
int main(){
    ll n,m;    cin>>n>>m;
    ll a,b,c;  cin>>a>>b>>c;
    ll k,w; cin>>k>>w;
    for(int i=1;i<=k;i++)
        for(int j=1;j<=k;j++)
            cin>>v[i][j];
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>maps[i][j];
            if(maps[i][j]==1)  life[i][j]=a;
            else if(maps[i][j]==2)  life[i][j]=b;
            else if(maps[i][j]==3)  life[i][j]=c;
        }
    }
    int q;  cin>>q;
    while(q--){
        int id,x,y;    cin>>id>>x>>y;
        if(id==1){
            for(int i=x-k/2,ii=1;i<=x+k/2,ii<=k;i++,ii++)
                for(int j=y-k/2,jj=1;j<=y+k/2,jj<=k;j++,jj++){
                    if(i<=0 || i>n || j<=0 || j>m)    continue;
                    if(life[i][j]){
                        if(life[i][j]>v[ii][jj])    life[i][j]-=v[ii][jj];
                        else    life[i][j]=0;
                    }
                }
        }
        else if(id==0){
            for(int i=x-k/2,ii=1;i<=x+k/2,ii<=k;i++,ii++)
                for(int j=y-k/2,jj=1;j<=y+k/2,jj<=k;j++,jj++){
                    if(i<=0 || i>n || j<=0 || j>m)    continue;
                    if(life[i][j]){
                        if(life[i][j]>v[ii][jj])    life[i][j]-=v[ii][jj];
                        else    life[i][j]=0;
                    }
                    for(int d=0;d<8;d++){
                        int xx=dx[d]+i,yy=j+dy[d];
                        if(xx<=0||yy<=0||xx>n||yy>m) continue;
                        if(life[xx][yy]){
                            if(life[xx][yy]<=w) life[xx][yy]=0;
                            else life[xx][yy]-=w;
                    }
                }
                }
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(maps[i][j]==1){
                 if(!life[i][j])    d_sum++;
                 sum+=(a-life[i][j]);
            }
            else if(maps[i][j]==2){
                 if(!life[i][j])    f_sum++;
                 sum+=(b-life[i][j]);
            }
            else if(maps[i][j]==3){
                 if(!life[i][j])    t_sum++;
                 sum+=(c-life[i][j]);
            }
    cout<<d_sum<<' '<<f_sum<<' '<<t_sum<<endl;
    cout<<sum<<endl;
    return 0;
}


H. 程序设计:字符串(模拟 + 取模)

原题链接:https://nanti.jisuanke.com/t/43122

  • 思路: 先把字符串转换为 26 进制,转换的过程要对 m 取模,然后双重循环暴力遍历,对任意两个字符进行转换,把转换后的字符串与原始字符串的差值加上原始字符串的值,再加上 m (为了防止出现负数的情况,但数据比较少,没考虑这种情况),判断是否为 m 的倍数。这道题的难点我觉得在于取模,每一步能取模的都要取模,不然只能通过 6 个样例。

Code:

import java.util.Scanner;
public class Main{
	static long m;
	static long[] a = new long[2010];
	static long change(String s) {
		long ans=0;
		for(int i=0;i<s.length();i++)
			ans=(ans*26+s.charAt(i)-'A')%m;
		return ans;
	}
    public static void main(String[] args){
    	Scanner cin = new Scanner(System.in);
    	String str = cin.next();
    	m = cin.nextInt();
    	int len = str.length();
    	a[len-1]=1;
    	for(int i=len-2;i>=0;i--)
    		a[i]=a[i+1]*26%m;
    	long ans = change(str);
    	if(ans==0) {
    		System.out.println("0 0");
    		return;
    	}
    	for(int i=0;i<len;i++) {
    		for(int j=i+1;j<len;j++) {
    			long res = (str.charAt(j)-str.charAt(i))*a[i]+(str.charAt(i)-str.charAt(j))*a[j];
    			if((ans+res+m)%m==0) {	//加上m防止出现负数
    				System.out.println(++i + " " + ++j);	//要用双引号
    				return;
    			}
    		}
    	}
    	System.out.println("-1 -1");
    }
}


发布了123 篇原创文章 · 获赞 57 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44668898/article/details/104034076