倪文迪陪你学蓝桥杯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\times5^j\times7^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);
    }
}

posted on 2021-01-15 15:28  罗勇军999  阅读(189)  评论(0编辑  收藏  举报

导航