【算法随记】C(n,m)不越界但A(n,m)越界;C(n,1)+C(n,3)+C(n,5)...等二项式定理;“memset”: 找不到标识符

https://codeforces.com/contest/893/problem/E

C(n,m)不越界但A(n,m)越界的解决方案

C(n,m) = A(n,m) / (n-m)!

这题要模1e9+7,但是只有加减乘能模,除法模不了。所以这个A(n,m)要存原值,原值也太大了,爆 long long

要是能不要除法,全是乘法就好了

法一:拆成多个质数相乘

先算A(n,m)里有多少个2 3 5 7,再减去(n-m)!中2 3 5 7的个数,最后把剩下的乘起来

long long C(int n, int m){
    long long ret=1;
 
    unordered_map<int,int> table;
    for(int x=n;x>m;x--){
        int tmpx=x;
        for(int i=2;i<=tmpx;i++){
            if(tmpx%i==0){
                int tmpcnt=1;
                tmpx=tmpx/i;
                while(tmpx%i==0 && tmpx){
                    tmpcnt++;
                    tmpx/=i;
                }
                table[i]+=tmpcnt;
            }
        }
    }
    for(int x=n-m;x>=1;x--){
        int tmpx=x;
        for(int i=2;i<=tmpx;i++){
            if(tmpx%i==0){
                int tmpcnt=1;
                tmpx=tmpx/i;
                while(tmpx%i==0 && tmpx){
                    tmpcnt++;
                    tmpx/=i;
                }
                table[i]-=tmpcnt;
            }
        }
    }
 
    for(auto it=table.begin(); it!=table.end();it++){
        int x=it->first;
        int cnt=it->second;
        ret=(ret*quickpower(cnt, x))%MOD;
    }
    return ret%MOD;
}

法二:除法转乘法

A / B ( m o d M ) ≡ A ∗ B M − 2 ( m o d M ) A/B \pmod{M} ≡ A*B^{M-2} \pmod {M} A/B(modM)ABM2(modM)

费马小定理:若M是质数,且B、M互质,那么B^(M-1) mod M = 1
M自己就是质数,当然与B互质
A/B mod M
= A/B mod M * 1
= A/B mod M * B^(M-1) mod M
= A*B^(M-2) mod M

理论:逆元

逆元:bx ≡ 1 (mod M) ,称 x 是 a mod M 的逆元
(a / b) mod M = a * x mod M

(a / b) mod M
= (a / b) * 1 mod M
= (a / b) * (b * x) mod M
= a * x mod M

而 x(inv(b)) 的值:x ≡ b^{M-2} (mod M)

因为 b x ≡ 1 ( m o d M ) bx \equiv 1 \pmod M bx1(modM)
所以 b x ≡ b M − 1 ( m o d M ) bx \equiv b^{M-1} \pmod M bxbM1(modM)(根据 费马小定理);
所以 x ≡ b M − 2 ( m o d M ) x \equiv b^{M-2} \pmod M xbM2(modM)

C(n,m)模板

C(n,m) mod M
= n! / m! / (n-m)! mod M
= n! * inv(m!) * inv((n-m)!) mod M

// f 阶乘,inv 逆元

long long f[MAXN],inv[MAXN];
long long quickpower(long long a, long long b){...}
void init()
{
	f[0]=inv[0]=1;
	for(long long i=1; i<maxn; i++)
	{
		f[i]=f[i-1]*i%MOD;
		inv[i]=quickpower(f[i], MOD-2);
	}
}
 
long long C(long long n, long long m)
{
	return f[n] * inv[n-m]%MOD * inv[m]%MOD;
}

二项式定理

C ( n , 0 ) + C ( n , 1 ) + C ( n , 2 ) + . . . + C ( n , n ) = 2 n C(n,0)+C(n,1)+C(n,2)+...+C(n,n) = 2^n C(n,0)+C(n,1)+C(n,2)+...+C(n,n)=2n
(1+x)^n,给x赋值为1

C ( n , 1 ) + C ( n , 3 ) + C ( n , 5 ) + . . . = 2 n − 1 C(n,1)+C(n,3)+C(n,5)+... = 2^{n-1} C(n,1)+C(n,3)+C(n,5)+...=2n1
C ( n , 0 ) + C ( n , 2 ) + C ( n , 4 ) + . . . = 2 n − 1 C(n,0)+C(n,2)+C(n,4)+... = 2^{n-1} C(n,0)+C(n,2)+C(n,4)+...=2n1
(1+x)^n,给x赋值为-1

“memset”: 找不到标识符

#include

你可能感兴趣的:(算法,c语言,开发语言)