我有两个序列:
1
8 27 64 125 ...
2
1 2 3 4 5 6 ....
现在从 1 中取出一个元素,从 2 中取出另一个元素,然后再将它们删除。重复这个。安排按递增顺序获得的数字。
8 16 24 27 32 40 48 54 56 64 64 ...
我们如何有效地找到n
这个新序列的数量?
答案 0 :(得分:1)
如果结果中没有重复元素,那么我将使用修改后的 Eratosthenes Sieves 标记所有最终序列号,然后创建系列本身的表格。这里有小的 C ++ 示例:
// globals
const int N0=4;
const int N1=6;
const int N2=N0*N1;
const int M=(N0+2)*(N0+2)*(N0+2)*N1;
int f0(int x) { x+=2; return x*x*x; } // x = <0,N0)
int f1(int x) { x+=1; return x; } // x = <0,N1)
int f2[N2],n; // x = <0,n )
// locals
int x,y;
BYTE soe[M+1];
AnsiString txt="";
// debug print series
for (txt+="f0(x) = ",x=0;x<N0;x++) { txt+=f0(x); txt+=" "; } txt+="\r\n";
for (txt+="f1(x) = ",x=0;x<N1;x++) { txt+=f1(x); txt+=" "; } txt+="\r\n";
tbeg();
// compute sieve
for (x=0;x<=M;x++) soe[x]=0;
for (x=0;x<N0;x++)
for (y=0;y<N1;y++)
soe[f0(x)*f1(y)]=1;
// reorder it to table
for (x=0,n=0;x<=M;x++)
if (soe[x]) { f2[n]=x; n++; }
tend(); txt+="computed in "+tstr(1)+"\r\n";
// debug print ordered series as function of x ... counting from 0
for (txt+="f2(x) = ",x=0;x<n;x++) { txt+=f2[x]; txt+=" "; } txt+="\r\n";
Form1->mm_log->Lines->Add(txt);
结果:
f0(x) = 8 27 64 125
f1(x) = 1 2 3 4 5 6
computed in [ 0.003 ms]
f2(x) = 8 16 24 27 32 40 48 54 64 81 108 125 128 135 162 192 250 256 320 375 384 500 625 750
只需忽略tbeg(),tend(),tstr()
和字符串Form1->mm_log,txt
内容或重写到您的平台/ IDE 。这还没有优化,可以进行很多改进...例如,您可以使用每个筛位元素的单位而不是BYTE
,甚至可以避免在内存中使用整个筛选表(通过巧妙的排序/分区子结果)
如果输出中存在重复项,那么您需要使用筛子作为元素的计数器而不仅仅是布尔值并相应地重建它。