【Java/补题/牛客/ACM赛制】2022年“蓝桥杯”上海理工大学校选赛(重现赛)

题目链接

2022年“蓝桥杯”上海理工大学校选赛(重现赛)

知识一览

01 - 数学/模拟
02 - 背包问题
03 - 质因数/dfs搜索
04 - 二分/并查集

题目列表

快输

    static class FastReader{
        BufferedReader br;
        StringTokenizer st;
        String tmp;

        public FastReader() {
            br=new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while(st==null||!st.hasMoreElements()) {
                try {
                    st=new StringTokenizer(br.readLine());
                }catch(IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong(){return Long.parseLong(next());}

        String nextLine() {
            String str="";
            try {
                str=br.readLine();
            }catch(IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        boolean hasNext(){
            if(st!=null&&st.hasMoreTokens())return true;
            try {
                tmp=br.readLine();
                st=new StringTokenizer(tmp);
            }catch(IOException e) {
                return false;
            }
            return true;
        }
    }

    static PrintWriter out=new PrintWriter(
            new BufferedWriter(new OutputStreamWriter(System.out)));
    static FastReader sc=new FastReader();

C - KartRider(数学/模拟)

题目链接:C
题目描述
已知游乐场有两条卡丁车赛道,赛道1的起点到终点距离为n,赛道2的起点到终点距离为m。
区别于传统的卡丁车,这里的卡丁车采用自动驾驶技术,且驾驶员不能在行驶过程中改变车子速度。
车子的速度遵循如下规律:第1秒内速度为1,第2秒内速度为2… 第 k秒内速度为k,车子的移动时间每增加1秒,其速度也加1。
此外,车子运动过程中可以在整数秒点人为改变运动方向,可以向前,也可以向后,也就是说:车手不能在0.5这种小数秒点改变车子的运动方向。
而且车子一旦启动,就不能在到达终点之前停止运动(必须在整数秒点到达终点,非整数秒点经过终点不被认作到达终点)。
经过石头剪刀布,Tari 选择在赛道1上驾驶赛车,Erini 选择在赛道2上驾驶赛车。
假设他们都采用了最佳策略,问:谁能用更短的时间到达终点,输出胜利者的名字和所用时间;如果两个人打成平手,输出 “Draw”。
输入描述:
输入两个正整数n和m,分别表示 Tari 和 Erini 从出发位置到终点的距离(0≤n,m≤10^9)。
输出描述:
输出胜利者的姓名和他到达终点时所用时间,中间用空格隔开;如果同时到达终点,输出"Draw"。
示例1
输入
3 2
输出
Tari 2
说明
Tari 的最佳驾驶策略:第 1 秒到达 1,第 2 秒到达 3(因为第 2 秒内卡丁车的速度为 2),所需时间为 2 秒。
Erini 的最佳驾驶策略:第 1 秒到达 1,然后第 2 秒反向行驶到 -1,第 3 秒再正向行驶到 2(2=1-2+3),所需时间为 3 秒。
示例2
输入
10 10
输出
Draw

	public static void main(String[] args) {
        //int T=sc.nextInt();
        int T=1;
        while(T-->0){
            solve();
        }
    }
    private static void solve(){
        long n=sc.nextLong(),m=sc.nextLong();
        long ans1=f(n),ans2=f(m);
        if(ans1<ans2){
            out.printf("%s %d\n","Tari",ans1);
        }else if(ans1==ans2){
            out.printf("Draw\n");
        }else{
            out.printf("%s %d\n","Erini",ans2);
        }
        out.flush();
    }
    private static long f(long a){
        if(a==0)return 0;
        long res=0;
        for(int i=1;;i++){
            res+=i;
            if(res>=a){
                long t=res-a;
                if((t&1)==0)return i;
                else if((i&1)==1) return i+2;
                else return i+1;
            }
        }
    }

F - Archery(背包问题)

题目链接: F
题目描述
比赛规则如下:运动场上有n个箭靶,编号为1-n,射中编号为i 的箭靶可以得到i×10分(i∈[1,n])。
但如果累计射中编号为i的箭靶靶心 ai次,那么选手可以额外获得bi的奖励分。同时比赛也规定,箭靶i最多被射中ai次,超出 ai不计分。
集训队的小明报名参加了本项射箭比赛,现在他邀请聪明的你帮他计算一下,他最少需要射出几箭,才能保证他的得分不低 k。
如果小明无论射出多少箭都无法获得大于等于k的得分,那么输出"wa"。
输入描述:
第1行输入正整数n,kn,k(1≤n≤10,10≤k≤10^9),表示运动场内箭靶的数量以及小明在射箭比赛中的最少得分。
第 2−n+1行每行输入两个正整数ai,bi(1≤ai≤100,10≤bi≤10^5),中间用空格隔开,含义如上文所述。
输出描述:
输出答案。
示例1
输入
2 70
3 50
5 80
输出
3
说明
小明可以选择在编号为 1 的箭靶上射箭 3 次,在得到基础分 30 分的前提下,他还可以得到奖励分 50 分,总分 80 分\geq k≥k,这是最佳策略,答案等于 3。
示例2
输入
2 40
3 50
5 80
输出
2
说明
小明可以选择在编号为2的箭靶上射箭 2 次,得分为2\times 20=40\geq k2×20=40≥k,此举为最佳策略,答案等于 2。

	public static void main(String[] args) {
        //int T=sc.nextInt();
        int T=1;
        while(T-->0){
            solve();
        }
    }
    private static void solve(){
        int n=sc.nextInt();
        long k=sc.nextLong();
        int a[]=new int[n+1],b[]=new int[n+1];
        int sum=0;
        for(int i=1;i<=n;i++) {
            a[i]=sc.nextInt();
            b[i]=sc.nextInt();
            sum+=a[i];
        }
        int dp[]=new int[sum+1];
        for(int i=1;i<=n;i++) {
            for(int j=sum;j>=1;j--) {
                for(int m=1;m<a[i];m++) {
                    if(j>=m) dp[j]=Math.max(dp[j],dp[j-m]+10*i*m);
                }
                if(j>=a[i]) dp[j]=Math.max(dp[j],dp[j-a[i]]+10*i*a[i]+b[i]);
            }
        }
        boolean f=false;
        for(int i=0;i<=sum;i++) {
            if(dp[i]>=k) {
                out.println(i);f=true;break;
            }
        }
        if(!f)out.println("wa");
        out.flush();
    }

G - Function(质因数/dfs搜索)

G

	static long prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};//16 : 0-15
    static long ans=0,n;
    public static void main(String[] args) {
        int T=sc.nextInt();
        //int T=1;
        while(T-->0){
            solve();
        }
    }
    private static void solve(){
        ans=0;
        n=sc.nextLong();
        dfs(1,1,0,60);
        out.println(ans);
        out.flush();
    }
    static void dfs(long cnt,long cur,int idx,int M){
        if(idx==16)return;
        if(cnt>ans)ans=cnt;
        for(int i=1;i<=M;i++){
        //注意cur*prime[idx]可能爆long
            if(n/prime[idx]<cur) break;
            cur*=prime[idx];
            dfs(cnt*(i+1),cur,idx+1,i);
        }
    }

H - Tree(二分/并查集)

H

	static int n,s;
    static long c[]=new long[N];
    static int a[]=new int[N],f[]=new int[N],u[]=new int[N],v[]=new int[N],d[]=new int[N];
    public static void main(String[] args) {
        //int T=sc.nextInt();
        int T=1;
        while(T-->0){
            solve();
        }
    }
    private static void solve(){
        n=sc.nextInt();//n个节点的树
        s=sc.nextInt();//需要获取价值总和至少为s的宝石
        for(int i=2;i<=n;i++) a[i]=sc.nextInt();//编号 2-n 节点上的宝石价值
        for(int i=1;i<n;i++) {//从节点u经过链duv走到节点v
            u[i]=sc.nextInt();
            v[i]=sc.nextInt();
            d[i]=sc.nextInt();
        }
        int l=0,r=(int)2e9,mid;
        while(l<=r){
            mid=l+r>>1;
            if(check(mid))r=mid-1;
            else l=mid+1;
        }
        out.println(l);
        out.flush();
    }
    static int find(int x){
        if(f[x]!=x)f[x]=find(f[x]);
        return f[x];
    }
    static void merge(int x,int y){
        int fx=find(x),fy=find(y);
        f[fx]=fy;
        c[fy]+=c[fx];
    }

    static boolean check(int mid){
        for(int i=1;i<=n;i++) {
            f[i]=i;
            c[i]=a[i];
        }
        for(int i=1;i<n;i++){
            if(mid>=d[i]) merge(u[i],v[i]);
        }
        return c[find(1)]>=s;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值