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
到x星球旅行的游客都被发给一个整数,作为游客编号。
x星的国王有个怪癖,他只喜欢数字3,5和7。
国王规定,游客的编号如果只含有因子:3,5,7,就可以获得一份奖品。
前10个幸运数字是:3 5 7 9 15 21 25 27 35 45,因而第11个幸运数字是:49
小明领到了一个幸运数字 59084709587505。
去领奖的时候,人家要求他准确说出这是第几个幸运数字,否则领不到奖品。
请你帮小明计算一下,59084709587505是第几个幸运数字。
填空,送分?
59084709587505这个数不算很大,C++的unsigned long long整型,最大值是 2 64 − 1 = 18446744073709551615 2^{64}-1=18446744073709551615 264−1=18446744073709551615。
这个系列的数可以表示为 3 i × 5 j × 7 k 3^i\times5^j\times7^k 3i×5j×7k,搜索所有不超过范围的 i 、 j 、 k i、j、k i、j、k组合即可。
Python不用担心大数,所以循环时顺便取个很大的范围作为终止条件就好了,下面代码中的 3 50 3^{50} 350肯定超过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 )
由于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.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)
下面给出C++的几种实现,懒得解释。
#include
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;
}
//new oj User: 190101041
#include
#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++;
}
}
//new oj User: 311706000426
#include
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;
}
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);
}
}
//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);
}
}