[Blue Bridge Cup] [Ugly Number] [Algorithm Optimization] What is the lucky number

Topic link

https://www.luogu.com.cn/problem/U136049

I'm just a porter of nature, and this topic is a real one of the Blue Bridge Cup. I published a few test data and put it in Luogu's personal question bank.

Title description

  Visitors who travel to planet x are issued an integer as the visitor number. The king of X star has a quirk, he only likes the numbers 3, 5 and 7. The king stipulated that if the number of a visitor only contains factors: 3, 5, 7, they can get a prize.

  Let’s look at the top 10 lucky numbers: 3 5 7 9 15 21 25 27 35 45. So the 11th lucky number is: 49

  Xiao Ming received a lucky number x. When he went to receive the prize, he was asked to say exactly which lucky number this was, otherwise he would not receive the prize.

Input format

The lucky number x received by Xiao Ming. 1 <= x <10^14.

Output format

A positive integer, which means this is the lucky number

Sample input and output

Enter #1 to copy

49

Output #1 copy

11

Instructions/tips

1 <= x < 10^14

Solution 1

Maintain a count variable, violent enumeration from 3 to x, each number is judged whether it is a lucky number, if it is a lucky number, the count variable +1.

The difficulty lies in how to judge whether a number is a lucky number. Since the factors of a lucky number are only 3, 5, and 7. So just keep it divided by 3 until it can't divide 3, then keep dividing by 5 until it can't divide 5, and then keep dividing by 7 until it can't divide 7. If the final result is 1, the original number is a lucky number.

But for x up to 10^14, obviously for such a data size, this algorithm will time out.

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

typedef long long ll;

int main()
{
	
	ll x;
	scanf("%lld", &x);
	
	int ans=0;
	for(ll i=3; i<=x; i++)
	{
		ll t=i;
		while(t%3==0)
			t /= 3;
		
		while(t%5==0)
			t /= 5;
		
		while(t%7==0)
			t /= 7;
		
		if(t==1)
		{
			ans++;
			if(i==x)
				break;
		}
	}
		
	printf("%d", ans);
	
	return 0;
}

Solution 2

From Orz, a fierce woman. . . x=3^{a}\times 5^{b}\times 7^{c}, Then you can enumerate the order and count the number 3^{a}\times 5^{b}\times 7^{c}\leqslant x of species through a triple loop  . But two issues need to be paid attention to

1. pow(3,a)*pow(5,b)*pow(7,c) may return beyond long long, so don't use long long to receive. Use double type to receive, and the return value of pow() itself is double

2. Why the condition in if is <instead of <=? Because there are so many enumerations that count x=1 (in fact, this is illegal), not taking the equal sign (not counting the case equal to x) just offset

#include<stdio.h>
#include<math.h>
int main(void) {
	long int n,m;
	scanf("%ld",&n);
	int a,b,c,count=0;
	for(a=0 ; pow(3,a)<n ; a++ ) {
		for(b=0 ; pow(5,b)<n ; b++) {
			for(c=0 ; pow(7,c)<n ; c++) {
				if(pow(3,a)*pow(5,b)*pow(7,c)<n) {
					count++;
				}
			}
		}
	}
	printf("%d",count);
	return 0;
}

 Solution 3

Assuming that the first i-1 lucky numbers are known, how to deduce the i-th lucky number? Obviously the i-th number can be inferred from the first i-1 number. The i-th number may be obtained by multiplying one of the first i-1 numbers by 3, or it may be obtained by multiplying one of the first i-1 numbers by 5, or it may be the first i-1 Multiply one of the numbers by 7 to get. It's not easy to express, it's easier to understand by looking at the code directly.

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

typedef long long ll;

vector<ll> num;

// 求 num[ num.size() ] 的待定值 
// 返回一个大于 num[ num.size()-1 ] 的待定值 
// 可用二分法优化,但没必要 
ll getNum(int key) 
{
	for(int i=0; i<num.size(); i++)
	{
		ll t = num[i]*key;
		if(t > num[ num.size()-1 ])
			return t;
	}
}

int main()
{
	num.push_back(3);
	num.push_back(5);	
	num.push_back(7);
	
	ll x;
	scanf("%lld", &x);
	
	while(num[ num.size()-1 ] < x) 
	{
		ll a = getNum(3);
		ll b = getNum(5);
		ll c = getNum(7);
		ll t = min(a, min(b, c));
		num.push_back(t);
	} 
	
	
	printf("%d", num.size());
	
	return 0;
}

Solution 4

Obviously, getNum() for solution 3 can be optimized by dichotomy! The time-consuming comparison, the change is not big, because for the largest x in the test data, the number of elements in the variable-length array num is only about 2000, so the effect of this optimization is not very obvious.

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

typedef long long ll;

vector<ll> num;

// 二分法 
ll getNum(int key) 
{
	int l=0, r=num.size()-1;
	
	while(l<r)
	{
		int m=(l+r)/2;
		if (num[m]*key <= num[ num.size()-1 ]) 
			l=m+1;
		else 
			r=m;
	}
	return num[r]*key;
}

int main()
{
	num.push_back(3);
	num.push_back(5);	
	num.push_back(7);
	
	ll x;
	scanf("%lld", &x);
	
	while(num[ num.size()-1 ] < x) 
	{
		ll a = getNum(3);
		ll b = getNum(5);
		ll c = getNum(7);
		ll t = min(a, min(b, c));
		num.push_back(t);
	} 
	
	
	printf("%d", num.size());
	
	return 0;
}

 

Guess you like

Origin blog.csdn.net/qq_43290318/article/details/109226775