Solution in C# using a class for computations modulo 10
IntuitionI noticed the relation to Pascals triangles. I hoped using BigIntegers would suffice, but alas.ApproachThis solution uses the same approach as others I
# Intuition
I noticed the relation to Pascals triangles. I hoped using BigIntegers would suffice, but alas.

# Approach
This solution uses the same approach as others I've examined. However it is the only one in C#.

We have to compute pascal's triangle modulo 10. This is tricky because you can't just divide modulo 10 (because 10 is not a prime, ask ChatGPT for more information). We get around this by introducing the class NumberModulo10. This class supports multiplication and division modulo 0. It qas quite finicky to write, it needed tests.

The idea behind NumberModulo10 is to keep track how many factors 2 and 5 the numbers has and store the remainder modulo 10. Creation and multiplication is easy to implement. However, division & conversion to an int is harder.

For division we have to compute the inverse of the remainder. This isdone via a short switch statement.

For conversion to an integer the two's cause some complexities. Fortunately the sequence is kinda simple, [2, 4, 8, 16, 32, 64, 128]. So the sequence mod 10 becomes [2, 4, 8, 6, 2, ...], which we put in another switch statement.

# Complexity
- Time complexity: $$O(n log(n))$$
- Space complexity: $$O(n)$$

# Code
```csharp []
public class Solution {
    public bool HasSameDigits(string s) {
        InitializeFactorials();
        //TestModulo10Computations();

        var counts = ComputePermutationsModulo10_2(s.Length-1).ToArray();
        var digits = s.Select(character => character - '0').ToArray();
        
        var left = 0;
        for (var i = 0; i < digits.Length - 1; i++)
            left += digits[i] * counts[i];
        left = left % 10;
        
        var right = 0;
        for (var i = 0; i < digits.Length - 1; i++)
            right += digits[i +1] * counts[i];
        right = right % 10;

        return left == right;
    }

    internal static NumberModulo10[] Factorials = null;

    public IEnumerable<int> ComputePermutationsModulo10(int n)
    {
        BigInteger result = 1;

        yield return (int)result;
        for (var i = 1; i < n; i++)
        {
            result = result * (n-i);
            result /= i;
            yield return (int)(result % 10);
        }
    }

    internal void InitializeFactorials()
    {
        if (Factorials != null)
            return;

        var max = 100005;
        Factorials = new NumberModulo10[max + 1];
        Factorials[0] = new NumberModulo10(0, 0, 1);
        for (var i = 1; i <= max; i++)
            Factorials[i] = NumberModulo10.Mult(Factorials[i-1], NumberModulo10.Create(i));
    }

    internal IEnumerable<int> ComputePermutationsModulo10_2(int n)
    {
        for (var i = 0; i < n; i++)
            yield return NumberModulo10.Divide(Factorials[n-1], NumberModulo10.Mult(Factorials[i], Factorials[n-1-i])).ToNumber();
    }

    internal void TestModulo10Computations()
    {
        //TestCreation();
        //TestMult();
        TestKnownCaseInDetail();
        TestCombinations();
    }

    internal void TestCreation()
    {
        for (var t = 1; t < 20; t++)
            Console.WriteLine($"{t} {NumberModulo10.Create(t).ToNumber()}");
    }

    internal void TestMult()
    {
        for (var t = 1; t < 10; t++)
            Console.WriteLine($"{(t*t)%10} {NumberModulo10.Mult(NumberModulo10.Create(t), NumberModulo10.Create(t)).ToNumber()}");
    }

    internal void TestKnownCaseInDetail()
    {
        Console.WriteLine($"{Factorials[9]}, {NumberModulo10.Mult(Factorials[2], Factorials[7])}, {NumberModulo10.Divide(Factorials[9], NumberModulo10.Mult(Factorials[2], Factorials[7]))}");        
    }

    internal void TestCombinations()
    {
        Console.WriteLine(string.Join(" ", ComputePermutationsModulo10(9).Select(_ => _.ToString())));
        Console.WriteLine(string.Join(" ", ComputePermutationsModulo10_2(9).Select(_ => _.ToString())));
    }

    public record NumberModulo10(int Twos, int Fives, int Remainder)
    {
        public static NumberModulo10 Create(int number)
        {
            var twos = 0;
            var fives = 0;
            var remainder = number;

            while (remainder % 2 == 0)
            {
                twos += 1;
                remainder = remainder / 2;
            }

            while (remainder % 5 == 0)
            {
                fives += 1;
                remainder = remainder / 5;
            }

            return new NumberModulo10(twos, fives, remainder);
        }

        public static NumberModulo10 Mult(NumberModulo10 left, NumberModulo10 right) =>
            new NumberModulo10(left.Twos + right.Twos, left.Fives + right.Fives, (left.Remainder * right.Remainder) % 10);

        public static NumberModulo10 Divide(NumberModulo10 left, NumberModulo10 right) =>
            new NumberModulo10(left.Twos - right.Twos, left.Fives - right.Fives, (left.Remainder * Inverse(right.Remainder)) % 10);

        public int ToNumber()
        {
            if (Twos > 0 && Fives > 0)
                return 0;
            else if (Twos > 0)
            {
                return (Twos % 4) switch
                {
                    0 => (6 * Remainder) % 10,
                    1 => (2 * Remainder) % 10,
                    2 => (4 * Remainder) % 10,
                    3 => (8 * Remainder) % 10,
                };
            }
            else if (Fives > 0)
                return (5 * Remainder) % 10;
            else
                return Remainder;
        }
            
        internal static  int Inverse(int value)
        {
            return value switch
            {
                1 => 1,
                3 => 7,
                7 => 3,
                9 => 9,
                _ => throw new Exception($"{value} has no inverse modulo 10")
            };
        }
    }
}
```
['C#']