The Fermat's little theorem approach is a mathematically sensible one, and just mulitplying over and over by 7 mod 10^6 is the simplest code, but there's another approach you could take that is computationally efficient (but requires more complex code). First, note that when multiplying by 7 the last digit depends only on the last digit before (i.e. we're doing everything mod 10). We multiply repeatedly by 7 to get
7 (4)9 (6)3 (2)1 (0)7 ...
Okay, great, so if we want a 3, we start at 7^3 and go up every 7^4 from there. Now, we note that when multiplying by 7^4, the last two digits depend only on the last two digits of 7^4 and the last two digits of the previous answer. 7^4 is 2401. So in fact the last two digits will always be the same when going up by 7^4.
What about the last three? Well, 7^3 = 343 and 7^4 ends with 401, so mod 1000 we get
343 543 743 943 143 343
We've got our first three digits in column #2 (543), and we see that the the sequence repeats ever 5, so we should go up from there by 7^20.
We can play this trick over and over again: find how often the next block of digits repeats, find the right subsequence within that block, and then multiply up not by 7 but by 7^n.
What we're really doing is finding a (multiplicative) ring over the m'th digit, and then multiplying the sizes of all the rings together to get the span between successive powers that have the same N digits if we follow this method. Here's some Scala code (2.8.0 Beta1) that does just this:
def powRing(bigmod: BigInt, checkmod: BigInt, mul: BigInt) = {
val powers = Stream.iterate(1:BigInt)(i => (i*mul)%bigmod)
powers.take( 2+powers.tail.indexWhere(_ % checkmod == 1) ).toList
}
def ringSeq(digits: Int, mod: BigInt, mul: BigInt): List[(BigInt,List[BigInt])] = {
if (digits<=1) List( (10:BigInt , powRing(mod,10,mul)) )
else {
val prevSeq = ringSeq(digits-1, mod, mul)
val prevRing = prevSeq.head
val nextRing = powRing(mod,prevRing._1*10,prevRing._2.last)
(prevRing._1*10 , nextRing) :: prevSeq
}
}
def interval(digits: Int, mul: Int) = {
val ring = ringSeq(digits, List.fill(digits)(10:BigInt).reduceLeft(_*_), mul)
(1L /: ring)((p,r) => p * (r._2.length-1))
}
So, if we've found one case of the digits that we want, we can now find all of them by finding the size of the appropriate ring. In our case, with 6 digits (i.e. mod 10^6) and base 7, we find a repeat size of:
scala> interval(6,7)
res0: Long = 5000
So, we've got our answer! 7^7 is the first, 7^5007 is the second, 7^10007 is the third, etc..
Since this is generic, we can try other answers...11^11 = 285311670611 (an 8 digit number). Let's look at the interval:
scala> interval(12,11)
res1: Long = 50000000000
So, this tells us that 11^50000000007 is the next number after 11^11 with the same initial set of 12 digits. Check by hand if you're curious!
Let's also check with 3^3--what's the next power of 3 whose decimal expansion ends with 27?
scala> interval(2,3)
res2: Long = 20
Should be 3^23. Checking:
scala> List.fill(23)(3L).reduceLeft((l,r) => {println(l*r) ; l*r})
9
27
81
243
729
2187
6561
19683
59049
177147
531441
1594323
4782969
14348907
43046721
129140163
387420489
1162261467
3486784401
10460353203
31381059609
94143178827
Yup!
(Switched code in edits to use BigInt so it could handle arbitrary numbers of digits. The code doesn't detect degenerate cases, though, so make sure you use a prime for the power....)