1 条题解

  • 0
    @ 2025-4-8 13:59:55

    解题思路

    要解决这个问题,我们需要生成由三个给定质数 ( p1, p2, p3 ) 的幂次乘积构成的数的序列,并按升序排列,然后找到序列中的第 ( i ) 个数。由于 ( i ) 可以很大(接近 ( 10^{18} )),直接生成所有可能的数并排序是不现实的,因为这样的序列会非常长。

    方法:优先队列(最小堆) + 集合去重

    我们可以使用优先队列(最小堆)来按升序生成序列中的数,同时使用一个集合来记录已经生成的数以避免重复。具体步骤如下:

    1. 初始化:将 ( 1 ) 放入优先队列和集合中。
    2. 生成序列:每次从队列中取出最小的数 ( x ),然后将其乘以 ( p1, p2, p3 ) 得到三个新的数。如果这些新数没有被生成过,就将它们加入队列和集合中。
    3. 计数:重复上述过程,直到取出第 ( i ) 个数(注意初始时 ( 1 ) 不算在序列中,所以可能需要调整计数)。

    优化

    由于 ( i ) 可能很大,直接生成前 ( i ) 个数可能会很慢。但题目保证输出小于 ( 10^{18} ),因此这种方法在合理的时间内是可以完成的。

    代码

    #include <iostream>
    #include <cstdio>
    using namespace std;
    long long int A[10008];
    inline long long int min(long long int a,long long int b)
    {
    	return a>b?b:a;
    }
    inline long long int min(long long int a,long long int b,long long int c)
    {
    	if(a>b)a=b;
    	if(a>c)a=c;
    	return a;
    }
    int main()
    {
    	long long int p1,p2,p3,n;
    	long long int i1,i2,i3;
    	long long int big;
    	while(cin>>p1>>p2>>p3>>n)
    	{
    		i1=i2=i3=1;
    		A[1]=min(p1,p2,p3);
    		A[0]=1;
    		for(long long int i=2;i<=n;i++)
    		{
    			big=A[i-1];
    			for(long long int j=0;j<i;j++)
    			{
    				if(A[j]*p1>A[i-1])
    				{
    					big=A[j]*p1;
    					break;
    				}
    			}
    			for(long long int j=0;j<i;j++)
    			{
    				if(A[j]*p2>A[i-1])
    				{
    					big=min(big,A[j]*p2);
    					break;
    				}
    			}
    			for(long long int j=0;j<i;j++)
    			{
    				if(A[j]*p3>A[i-1])
    				{
    					big=min(big,A[j]*p3);
    					break;
    				}
    			}
    			A[i]=big;
    		}
    		cout<<A[n]<<endl;
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    1546
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者