zoukankan      html  css  js  c++  java
  • 倪文迪陪你学蓝桥杯2021寒假每日一题:1.16日(2018省赛A组第4题)

    2021年寒假每日一题,2017~2019年的省赛真题。
    本文内容由倪文迪(华东理工大学计算机系软件192班)和罗勇军老师提供。
    后面的每日一题,每题发一个新博文,请大家每天蓝桥杯专栏: https://blog.csdn.net/weixin_43914593/category_10721247.html

    每一题提供C++、Java、Python三种语言的代码。
    由于Python强大威猛、编码简洁,所以后面的博文主要用Python代码解释,当然还是会(略带嫌弃地)附上C++和Java的代码。
    @

    2018省赛A组第4题,题目链接:
    第几个幸运数 http://oj.ecustacm.cn/problem.php?id=1362

    1、题目描述


    到x星球旅行的游客都被发给一个整数,作为游客编号。
    x星的国王有个怪癖,他只喜欢数字3,5和7。
    国王规定,游客的编号如果只含有因子:3,5,7,就可以获得一份奖品。
    前10个幸运数字是:3 5 7 9 15 21 25 27 35 45,因而第11个幸运数字是:49
    小明领到了一个幸运数字 59084709587505。
    去领奖的时候,人家要求他准确说出这是第几个幸运数字,否则领不到奖品。
    请你帮小明计算一下,59084709587505是第几个幸运数字。


    2、说明

      填空,送分?
      59084709587505这个数不算很大,C++的unsigned long long整型,最大值是(2^{64}-1=18446744073709551615)

    3、Python代码

    3.1 暴力搜

      这个系列的数可以表示为(3^i imes5^j imes7^k),搜索所有不超过范围的(i、j、k)组合即可。
      Python不用担心大数,所以循环时顺便取个很大的范围作为终止条件就好了,下面代码中的(3^{50})肯定超过59084709587505。

    cnt = 0
    for i in range(50):
        for j in range(50):
            for k in range(50):
                r1 = 3**i
                r2 = 5**j
                r3 = 7**k
                if r1*r2*r3 < 59084709587505:  #注意不是 <=
                    cnt += 1
    print(cnt )
    

    3.2 硬算+排序

      由于Python编码极其容易,即使硬算出所有3、5、7的倍数,然后再排序找到59084709587505的位置,也是很容易编码的。

    n = 59084709587505
    a = [1]           #放3、5、7的倍数
    k = 0
    while True: 
        for i in range(3, 8, 2):    #遍历3、5、7
            tmp = i*a[k]            #产生一个新数
            if tmp not in a:        #去重
                a.append(tmp)       #放进去
                a.sort()            #排序
            if tmp > 2**64:         #随便取一个够大的范围
                print(a.index(n))   #打印
                exit(0)
        k += 1
    

    3.3 优先队列+set去重

      上面“3.2 硬算+排序“的思路,可以用优先队列实现。每生成一个新数,就放进优先队列;每次从队列中弹出的数,都是最小的,相当于实现了排序。另外放进队列时用set去重。

    import queue
     
    q = queue.PriorityQueue()   #优先队列,由于排序
    s = set()                   #用于去重  
    q.put(1)    
    s.add(1)    
    cnt = 0
    while True:
        n = q.get()
        if n == 59084709587505:
            break
        cnt += 1
        for i in range(3, 8, 2):     #3、5、7
            t = n * i                #生成一个新数
            if t not in s:           #去重
                q.put(t)
                s.add(t) 
    print(cnt)
    

    4、C++代码

      下面给出C++的几种实现,懒得解释。

    4.1 暴力搜

    #include<bits/stdc++.h>
    using namespace std;
    int main(void){
        long long n = 59084709587505;
        int cnt = 0;
        for(int i=0;pow(3,i)<n;i++)    //注意不是 <=
            for(int j=0;pow(5,j)<n;j++)
                for(int k=0;pow(7,k)<n;k++)
                    if(pow(3,i)*pow(5,j)*pow(7,k)<n)
                        cnt++;
        cout<<cnt;
        return 0;
    }
    

    4.2 优先队列+mp去重

    //new oj User: 190101041
    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    typedef priority_queue<ll,vector<ll>,greater<ll> > pq;
    typedef map<ll,int> mp;
    mp vis;
    int sum[5]={3,5,7};
    int main(){
       ll tem=59084709587505;
     
        pq qu;
        qu.push(1);
        int ans=0;
        while(1){
            ll cnt=qu.top();
            qu.pop();
            if(cnt==tem){
               cout<<ans<<endl;
               break;
            }
            ll temcnt;
            for(int i=0;i<3;i++){
                temcnt=cnt*sum[i];
                if(vis[temcnt]==0){
                    qu.push(temcnt);
                    vis[temcnt]=1;
                }
            }
            ans++;
        }
    }
    

    4.3 set+upper_bound

    //new oj User: 311706000426
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    set<LL> se; 
    int main(){
        LL f = 1;
        LL a[3] = {3,5,7};
        while(1){
            for(int i=0;i<3;i++)
                if(f*a[i]<=59084709587505) 
                	se.insert(f*a[i]);
            f = *se.upper_bound(f);
            if(f>=59084709587505) 
            	break;
        }
        cout<<se.size();
     
        return 0;
    }
    

    5、Java代码

    5.1 暴力搜

    public class Main{
        public static void main(String[] args) {
            int count=0;
            long n=59084709587505L;
            for(int i=0;Math.pow(3,i)<n;i++){
                for(int j=0;Math.pow(5,j)<n;j++){
                    for(int k=0;Math.pow(7,k)<n;k++){
                        if(Math.pow(3,i)*Math.pow(5,j)*Math.pow(7,k)<n){
                            count++;
                        }
                    }
                }
            }
            System.out.println(count);
        }
    }
    

    5.6 优先队列+set去重

    //new oj User: coder370
    import java.util.*; 
    public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in) ;
            long n = 59084709587505L ; 
            int x=0,y=0,z=0 ; 
            long t=n ; 
            while(t%3==0) {t/=3;++x;}
            while(t%5==0) {t/=5;++y;}
            while(t%7==0) {t/=7;++z;}
            int mx=Math.max(x,y) ; 
            mx = Math.max(mx, z) ; 
            PriorityQueue<Long> q = new PriorityQueue<Long>() ; 
            Set<Long> st = new HashSet<Long>() ; 
            long[] num = {3,5,7} ; 
            for(int i=0 ; i<3 ;  ++i) {q.add(num[i]) ; st.add(num[i]);}
            int cnt=0 ; 
            while(q.isEmpty()==false) {
                long h = q.poll() ;
                ++cnt ; 
                if(h==n)    break ;
                for(int i=0 ; i<3 ; ++i) {
                    t = h*num[i] ; 
                    if(t>n)  continue ; 
                    if(st.contains(t)==false) {
                        q.add(t) ;
                        st.add(t) ; 
                    }
                }
            }
            System.out.println(cnt);
        }
    }
    
  • 相关阅读:
    有什么样的博客手机客户端
    v2ex thread record
    Screengrab! firefox截图插件
    现在看一次咳嗽感冒就差不多要1k了,恐怖
    海归人才网
    LinkedIn公司实现的实时搜索引擎Zoie
    xipian的php中文分词
    海归人才网
    idea
    snagit number stampsgood for ppt
  • 原文地址:https://www.cnblogs.com/luoyj/p/14282310.html
Copyright © 2011-2022 走看看