乘法逆元(除法取模可用)

134 阅读1分钟

例题

leetcode.cn/problems/co…

image.png

分析:

不难看出答案等于每个word的异构字符串个数的乘积,问题变成了如何求word的异构字符串个数

令word的长度为n,10^9 + 7为p

那么 ans=n!i=azcnt[i]!modpans = \frac{n!}{\prod_{i=a}^z{cnt[i]!}} \mod p

乘法取模都会,但是如何对除法取模?这里需要用到 乘法逆元 的知识

乘法逆元

定义:如果一个线性同余方程ax1(modp)ax \equiv 1 \pmod{p},则 xxamod pa\mod\ p 的逆元

快速幂解法:

因为 ax1(modp)ax \equiv 1 \pmod{p}

由费马小定理:axap1(modp)ax \equiv a^{p-1} \pmod{p}

所以:xap2(modp)x \equiv a^{p-2} \pmod{p}

所以:ans=n!i=azcnt[i]!p2modpans = {n!} * {\prod_{i=a}^z{cnt[i]!}} ^ {p - 2} \mod p

费马小定理

定义:若p为素数,gcd(a,p)=1gcd(a, p) = 1,则ap11(modp)a ^ {p - 1} \equiv 1 \pmod{p}

另一种形式 apa(modp)a^p \equiv a \pmod{p}

证明:

数学归纳法

显然 1p1(modp)1^p\equiv 1\pmod p,假设 apa(modp)a^p\equiv a\pmod p 成立,那么通过二项式定理有

(a+1)p=ap+(p1)ap1+(p2)ap2++(pp1)a+1(a+1)^p=a^p+\binom{p}{1}a^{p-1}+\binom{p}{2}a^{p-2}+\cdots +\binom{p}{p-1}a+1

因为 (pk)=p(p1)(pk+1)k!\binom{p}{k}=\frac{p(p-1)\cdots (p-k+1)}{k!} 1kp11\leq k\leq p-1 成立

在模 pp 意义下 (p1)(p2)(pp1)0(modp)\binom{p}{1}\equiv \binom{p}{2}\equiv \cdots \equiv \binom{p}{p-1}\equiv 0\pmod p

那么(a+1)pap+1(modp)(a+1)^p \equiv a^p +1\pmod p

将 apa(modp)a^p\equiv a\pmod p 带入得 (a+1)pa+1(modp)(a+1)^p\equiv a+1\pmod p 得证

代码

class Solution {

    int mod = (int) 1e9 + 7;

    public int countAnagrams(String s) {
        String[] arr = s.split(" ");
        int n = arr.length;
        long res = 1;
        for (int i = 0; i < n; i++) {
            res = res * func(arr[i]) % mod;
        }
        return (int) res;
    }

    public long func(String s) {
        int n = s.length();
        long mul = 1;
        long a = 1;
        int[] cnt = new int[26];
        for (int i = 0; i < n; i++) {
            char c = s.charAt(i);
            int j = c - 'a';
            cnt[j]++;
            mul = mul * (i + 1) % mod;
            a = a * cnt[j] % mod;
        }
        return mul * quickPow(a, mod - 2) % mod;
    }

    public long quickPow(long x, long y) {
        if (y == 0) return 1;
        long res = 1;
        if (y % 2 == 0) {
            res = quickPow(x * x % mod, y / 2);
        } else {
            res = res * x % mod;
            res = res * quickPow(x, y - 1) % mod;
        }
        return res;
    }

}