Problem:
Score : 300 points

Problem Statement

You are given an integer N. Among the integers between 1 and N (inclusive), how many Shichi-Go-San numbers (literally "Seven-Five-Three numbers") are there?

Here, a Shichi-Go-San number is a positive integer that satisfies the following condition:

When the number is written in base ten, each of the digits 7, 5 and 3 appears at least once, and the other digits never appear.

Constraints

1 \leq N < 10^9

N is an integer.

Input

Input is given from Standard Input in the following format:

N

Output

Print the number of the Shichi-Go-San numbers between 1 and N (inclusive).

Sample Input 1

575

Sample Output 1

4

There are four Shichi-Go-San numbers not greater than 575: 357, 375, 537 and 573.

Sample Input 2

3600

Sample Output 2

13

There are 13 Shichi-Go-San numbers not greater than 3600: the above four numbers, 735, 753, 3357, 3375, 3537, 3557, 3573, 3575 and 3577.

Sample Input 3

999999999

Sample Output 3

26484

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using BitArray = System.Collections.BitArray;
using BigInteger = System.Numerics.BigInteger;

namespace AtCoderProject
{
    public class Program
    {
        public object Calc()
        {
            var n = consoleReader.Int32();
            if (n < 357) return 0;
            var ketaNum = n.ToString().Length;
            var sum = 0;

            return Calc(n);
        }

        int Calc(int n)
        {
            if (n < 357) return 0;
            var nStr = n.ToString();
            var ketaNum = nStr.Length;
            var sum = ketaCache.Take(ketaNum).Sum();
            var d = (int)Math.Pow(10, ketaNum - 1);

            if (n < d * 3)
                return sum;
            if (n < d * 4)
            {
                for (int i = (int)Math.Pow(3, ketaNum - 1) - 1; i > 0; i--)
                {
                    var a = i;
                    var num = d * 3;
                    var p = 1;
                    var threeCount = 0;
                    var fiveCount = 0;
                    var sevenCount = 0;
                    for (int keta = 0; keta < ketaNum - 1; keta++, p *= 10, a /= 3)
                    {
                        int x = 0;
                        switch (a % 3)
                        {
                            case 0:
                                x = 3;
                                threeCount++;
                                break;
                            case 1:
                                x = 5;
                                fiveCount++;
                                break;
                            case 2:
                                x = 7;
                                sevenCount++;
                                break;
                            default:
                                break;
                        }

                        num += p * x;
                    }
                    if (fiveCount > 0 && sevenCount > 0 && num <= n)
                        sum++;
                }
                return sum;
            }
            if (n < d * 5)
                return sum + ketaCache[ketaNum] / 3;
            if (n < d * 6)
            {
                sum += ketaCache[ketaNum] / 3;
                for (int i = (int)Math.Pow(3, ketaNum - 1) - 1; i >= 0; i--)
                {
                    var a = i;
                    var num = d * 5;
                    var p = 1;
                    var threeCount = 0;
                    var fiveCount = 0;
                    var sevenCount = 0;
                    for (int keta = 0; keta < ketaNum - 1; keta++, p *= 10, a /= 3)
                    {
                        int x = 0;
                        switch (a % 3)
                        {
                            case 0:
                                x = 3;
                                threeCount++;
                                break;
                            case 1:
                                x = 5;
                                fiveCount++;
                                break;
                            case 2:
                                x = 7;
                                sevenCount++;
                                break;
                            default:
                                break;
                        }
                        num += p * x;
                    }
                    if (threeCount > 0 && sevenCount > 0 && num <= n)
                        sum++;
                }
                return sum;
            }
            if (n < d * 7)
                return sum + ketaCache[ketaNum] / 3 * 2;
            if (n < d * 8 - 7)
            {
                sum += ketaCache[ketaNum] / 3 * 2;
                for (int i = (int)Math.Pow(3, ketaNum - 1) - 1; i > 0; i--)
                {
                    var a = i;
                    var num = d * 7;
                    var p = 1;
                    var threeCount = 0;
                    var fiveCount = 0;
                    var sevenCount = 0;
                    for (int keta = 0; keta < ketaNum - 1; keta++, p *= 10, a /= 3)
                    {
                        int x = 0;
                        switch (a % 3)
                        {
                            case 0:
                                x = 3;
                                threeCount++;
                                break;
                            case 1:
                                x = 5;
                                fiveCount++;
                                break;
                            case 2:
                                x = 7;
                                sevenCount++;
                                break;
                            default:
                                break;
                        }

                        num += p * x;
                    }
                    if (threeCount > 0 && fiveCount > 0 && num <= n)
                        sum++;
                }
                return sum;
            }

            return sum + ketaCache[ketaNum];
        }



        static int[] ketaCache = new int[10];
        static Program()
        {
            for (int i = 3; i <= 9; i++)
            {
                ketaCache[i] += ketaNum(i);
            }
        }
        static int ketaNum(int i) => (int)Math.Pow(3, i) - 3 * ((int)Math.Pow(2, i) - 1);

        const int mod = 1000000007;
        private readonly ConsoleReader consoleReader;
        public Program() : this(new ConsoleReader()) { }
        public Program(ConsoleReader consoleReader) { this.consoleReader = consoleReader; }
        static void Main() => Console.WriteLine(new Program().Calc());
        public static string MultiLine<T>(IEnumerable<T> source) => string.Join("\n", source);
    }

    public class ConsoleReader
    {
        public virtual string String() => Console.ReadLine(); public int Int32() => int.Parse(String()); public long Int64() => long.Parse(String()); public ulong UInt64() => ulong.Parse(String()); public double Double() => double.Parse(String()); public string[] Split() => String().Split().ToArray(); public int[] SplitInt32() => String().Split().Select(int.Parse).ToArray(); public long[] SplitInt64() => String().Split().Select(long.Parse).ToArray(); public ulong[] SplitUInt64() => String().Split().Select(ulong.Parse).ToArray(); public double[] SplitDouble() => String().Split().Select(double.Parse).ToArray(); public IEnumerable<string> Repeat(int count) { for (int i = 0; i < count; i++) yield return String(); }
        public IEnumerable<int> RepeatInt32(int count) { for (int i = 0; i < count; i++) yield return Int32(); }
        public IEnumerable<long> RepeatInt64(int count) { for (int i = 0; i < count; i++) yield return Int64(); }
        public IEnumerable<string[]> RepeatSplit(int count) { for (int i = 0; i < count; i++) yield return Split(); }
        public IEnumerable<int[]> RepeatSplitInt32(int count) { for (int i = 0; i < count; i++) yield return SplitInt32(); }
    }
}