猜猜我的手机号码?
11位数字,其中0123456789都在里面,可以分解成两个不小于10000的素数相乘?看看有多少个候选号码?
善于在生活中提出问题 貌似不容易做出来呢 从一万开始往上算到一百万,用素数一个一个往上试验不就行了。
应该没有什么好方法的,整个运算量吓人。 用0123456789和一个p所组成的数字不多,然后可以否定各位为偶数、5的情况,剩下的数不会很多,然后逐个分解。
可惜我不懂暴力破解。看看大家能否破解出来? 提供一个方法:
先用下面的方法筛一下:
计算i*j (1<=i<=j<10000), 只保存i*j中末4位中最多有一个数字出现2次,其余数字只出现一次的(i,j)对. with sp as(
select 3 s from dual union all
select 5 from dual union all
select 7 from dual union all
...
select 1399 from dual union all
select 1409 from dual union all
select 1423 from dual),-- 3~sqrt(2E10/1E4=2000000)的素数表,用来判断a.p,b.p是否素数的整数倍,2不用判断
pr as (select 9999+level*2 p from dual connect by level<=1000000),--大的奇数因数 10001~2000000
pr2 as (select 9999+level*2 p from dual connect by level<=(141439-9999)/2)--小的奇数因数 10001~141439
select a.p*b.p n from pr a,pr2 b
where b.p>=1E10/a.p and b.p<=2E10/a.p
and not exists(select 1 from sp c where mod(a.p,c.s)=0)
and not exists(select 1 from sp c where mod(b.p,c.s)=0)
/*假定是中国手机号都是1开头*/
and a.p*b.p>=1E10 and a.p*b.p<2E10
and instr(to_char(a.p*b.p),'0')>1
--and instr(to_char(a.p*b.p),'1')>1 /*第一位必须是1,因此不用判断*/
and instr(to_char(a.p*b.p),'2')>1
and instr(to_char(a.p*b.p),'3')>1
and instr(to_char(a.p*b.p),'4')>1
and instr(to_char(a.p*b.p),'5')>1
and instr(to_char(a.p*b.p),'6')>1
and instr(to_char(a.p*b.p),'7')>1
and instr(to_char(a.p*b.p),'8')>1
and instr(to_char(a.p*b.p),'9')>1
; 算出来一些了
...
10528645973
10578295643
10648593271
10452796853
10924168357
10538624597
10585463279
10826753459
10415628973
10677342859
11075829463
10461283957
10628524397
10683745297
10768943257
10798762543
10892756453
10375928467 这些比较象
13284607759
13287451069 太多了,已经超过9千行了,再加个限制条件 /*假定是中国手机号都是1开头,第2位是3 5 8*/
and a.p*b.p>=1E10 and a.p*b.p<2E10
and substr(to_char(a.p*b.p),2,1)IN('3','5','8')