首先題目給出一個定義,一個數具有productive property是指這個數是另一個數所有位上數字的乘積。如2是12各位上數字的乘積,80也是:80=2*2*2*5。
題目要求給出一個正整數i,求出按升序排列后第i個具有productive property的數是多少。題目保證結果不會大于10^18。
最直接的想法就是找出所有這樣的數,然后排序,按i輸出相應的數。
這里我走了一條彎路,一開始是想找出所有的數,這些數沒有大于10的質因子,但這樣就要打素數表,還要對一個數進行試除,時間復雜度比較高(從10試到10^18)。
其實反過來想,時間復雜度可以大大降低:這些數的因子只能是2,3,5,7,由這些因子所產生的合數數目肯定大大小于10^18。
簡單計算一下可以知道:2^59<10^18, 3^37<10^18, 5^25<10^18, 7^21<10^18。因此只要產生59*37*25*21<=1146075個數就夠了。
如何高效產生這些數呢?這里使用了類似DFS+剪枝的技術,設當前這個數為tmp, 則若tmp*c>10^18就不用再乘下去了,其中c是2,3,5,7其中某個數的冪次。具體見程序里的 init
#include <iostream>
#include <algorithm>

using namespace std;

__int64 b=1;
__int64 a[1146075];
__int64 f[4][60];
void init()


{
// i,j,k,l分別是2,3,5,7的冪次
int i,j,k,l,cnt=0;
// 預先計算階乘
b=1;
for(i=1;i<=18;i++) b*=10;
f[0][0]=f[1][0]=f[2][0]=f[3][0]=1;
for(i=1;i<=59;i++) f[0][i]=f[0][i-1]*2;
for(i=1;i<=37;i++) f[1][i]=f[1][i-1]*3;
for(i=1;i<=25;i++) f[2][i]=f[2][i-1]*5;
for(i=1;i<=21;i++) f[3][i]=f[3][i-1]*7;
// 產生所有質因子在10以內的數
__int64 tmp;

for(i=0;i<=59;i++)
{
tmp=f[0][i];

for(j=0;j<=37;j++)
{
if(tmp*f[1][j]>=b) break;
else tmp*=f[1][j];

for(k=0;k<=25;k++)
{
if(tmp*f[2][k]>=b) break;
else tmp*=f[2][k];

for(l=0;l<=21;l++)
{
if(tmp*f[3][l]>=b) break;
else a[cnt++]=tmp*f[3][l];
}
tmp/=f[2][k];
}
tmp/=f[1][j];
}
tmp/=f[0][i];
}
sort(a,a+cnt);
}

int main()


{
init();
int t,i;
scanf("%d",&t);

while(t--)
{
scanf("%d",&i);
printf("%I64d\n",a[i-1]);
}
return 1;
}