これまた難しい問題です。
f(123)=1+2+3=6
のように定義された関数f(x)がある。
問1
f(n10)=n
となる正の整数nを求めよ。
n=1はすぐに思いつくが、次はいくつだろうか。
n=82
8210=13744803133596058624
1+3+7+4+4+8+0+3+1+3+3+5+9+6+0+5+8+6+2+4=82
n=85
8510=19687440434072265625
1+9+6+8+7+4+4+0+4+3+4+0+7+2+2+6+5+6+2+5=85
n=94
9410=53861511409489970176
5+3+8+6+1+5+1+1+4+0+9+4+8+9+9+7+0+1+7+6=94
n=97
9710=73742412689492826049
7+3+7+4+2+4+1+2+6+8+9+4+9+2+8+2+6+0+4+9=97
n=106
10610=179084769654285362176
1+7+9+0+8+4+7+6+9+6+5+4+2+8+5+3+6+2+1+7+6=106
n=117
11710=480682838924478847449
4+8+0+6+8+2+8+3+8+9+2+4+4+7+8+8+4+7+4+4+9=117
のように見つかっていったのだが、これでおしまいなのかが不安が残る。
更に問題は難しくなっていく。
問2
f(nm)=n
となる正の整数m,nを求めよ。
問1はm=10で固定であったので、プログラミングはnのループだけを考えればよい。
ただ、nはいくつまで回せばよいのかが不安が残る。
問2は、nのループの内側にmのループを作ることになるのだろうが、mはいくつまで回せば漏れがないのかが難しい。
数学的な考証をする必要があるだろう。
例えば、
nmがk桁の整数だとして、n/kを求めると、各桁の平均が求まるだろう。
各桁は0から9までですから、(0+9)/2=4.5が平均である。
kをC言語風に求めるのであれば、
k = ceil(m*log10(n));
問1の解から、n/kを調べてみる。
n=82,m=10
8210=13744803133596058624
k=20
n/k=82/20=4.1
n=85
8510=19687440434072265625
k=20
n/k=85/20=4.25
n=94
9410=53861511409489970176
k=20
n/k=94/20=4.7
n=97
9710=73742412689492826049
k=20
n/k=97/20=4.85
n=106
10610=179084769654285362176
k=21
n/k=106/21=5.{047619}
n=117
11710=480682838924478847449
k=21
n/k=117/21=5.{571428571428}
のようにn/k=4.5近辺で見つかっていることがわかる。
n/kのレンジを定められれば良さそうな感じはするが、どうなんだろうか。
問2のプログラムを漏れがあっても良いと考えて適当に組んでみたところ、
1<n<10で
f(74)=7
f(83)=8
f(92)=9
のような解を見つけた。
n=7, m=4
74=2401
2+4+0+1=7
k=4
n/k=7/4=1.75
n=8, m=3
83=512
5+1+2=8
k=3
n/k=8/3=2.{6}
n=9, m=2
92=81
8+1=9
k=2
n/k=9/2=4.5
桁数が少ないと、平均よりも外れやすいとも言える。
9<n<100とレンジを広げてみると、
f(173)=17
f(183)=f(186)=f(187)=18
f(2013)=20
f(224)=22
f(254)=25
f(263)=26
f(273)=f(277)=27
f(284)=f(285)=28
f(317)=31
f(347)=34
f(355)=35
f(364)=f(365)=36
f(4013)=40
f(437)=43
f(456)=45
f(465)=f(468)=46
f(537)=53
f(546)=f(548)=f(549)=54
f(587)=58
f(638)=63
f(646)=64
f(687)=68
f(719)=71
f(8017)=f(8019)=80
f(819)=81
f(8210)=82
f(8510)=85
f(8613)=86
f(9019)=f(9020)=f(9021)=f(9022)=f(9028)=90
f(9114)=91
f(9410)=94
f(9710)=97
f(9811)=98
のように見つかる。
n=20, 40, 80, 90のとき、近隣のnのmよりもmの値が大きく感じる。
これはnの末尾に0が含まれるからだと考えた。
nの末尾の0の個数が1個で、
nmの末尾の0の個数はm個です。
n=20, m=13
2013=81920000000000000
k=17
n/k=20/17=1.{1764705882352941}
n/(k-m)=20/(17-13)=20/4=5
n=40, m=13
4013=671088640000000000000
k=21
n/k=1.{904761904761904761}
n/(k-m)=20/(21-13)=20/8=2.5
n=80, m=17
8017=225179981368524800000000000000000
k=33
n/k=80/33=2.{42}
n/(k-m)=80/(33-17)=80/16=5
n=80, m=19
8019=1441151880758558720000000000000000000
k=37
n/k=80/37=2.{162}
n/(k-m)=80/(37-19)=80/18=4.{4}
n=90, m=19
9019=13508517176729920890000000000000000000
k=38
n/k=2.{368421052631578947}
n/(k-m)=90/(38-19)=4.{736842105263157894}
n=90, m=20
9020=1215766545905692880100000000000000000000
k=40
n/k=90/40=2.25
n/(k-m)=90/(40-20)=90/20=4.5
n=90, m=21
9021=109418989131512359209000000000000000000000
k=42
n/k=90/42=2.{142857142857}
n/(k-m)=90/(42-21)=90/21=4.{285714}
n=90, m=22
9022=9847709021836112328810000000000000000000000
k=43
n/k=90/43=2.{093023255813953488372}
n/(k-m)=90/(43-22)=90/21=4.{285714}
n=90, m=28
9028=5233476330273605372135115210000000000000000000000000000
k=55
n/k=90/55=1.{63}
n/(k-m)=90/(55-28)=90/27=3.{3}
という感じで、おぼろげながらレンジがあるのが伺える。
99<n<1000のレンジでnの末尾に0が2個続くものを探してみると、
f(400160)=400
が見つかる。
nの末尾の0の個数が2個で、
nmの末尾の0の個数は2m個です。
m=160なので、320個も0が続きます。
400160=21359870359209100
82395021706169552114602704522356652769947041607822
21972578064055002296208693657600000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000.
計算通りです。
n=400, m=160
k=417
n/k=400/417≒0.96
n/(k-2m)=400/(417-320)=400/97≒4.12
こんな感じで、末尾に続く0の個数を考慮すれば、4.5の平均付近のレンジを小さく取れそうな感じがする。
さて、漏れなく見つけるにはどんなプログラムを組もうか。
因みに、今回は多倍長電卓LMを使ってみました。
自分で多倍長演算を実装してもいいのですが、LMは電卓といいつつも、C言語風なスクリプトも書けて、簡単に試せるというのは便利ですね。
ではでは