zoukankan      html  css  js  c++  java
  • BZOJ 3656: 异或 (组合数取模 CRT)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3656
    大意:经过一通推导,问题变成求$$inom N M mod P$$,其中N,M<=1e9, P<=1e5,P可以是合数。

    参考这位神犇的博客:http://blog.csdn.net/braketbn/article/details/50752153

    作为一个蒟蒻,稍微写一点自己的理解...

    如果P是素数,我们可以用lucas定理直接解决,那么P是合数应该怎么办呢?

    首先,考虑把P分解质因数,拆成$${p_0} ^ {k_0} {p_1}^{k_1} {p_2} ^ {k_2}...$$的形式,再对每一个p^k计算,最后用CRT(中国剩余定理)合并。

    然后就是怎么算组合数对质数的幂取模的问题了。我们设$$f(n)=prod_{i=1}^n i[imod p e0]mod {pk}$$,就是1~n中非p的倍数的积对pk取模,那么只要先把n!,m!,(n-m)!里的p的倍数的因子p全部提出来,然后求出f(n),f(m),f(n-m)的值就行了。

    求f(n)可以用递归,把n按照p^k分段,整段的可以一起算,零散的一段直接暴力计算,然后乘上f(n/p),表示所有的p的倍数除以p后f的值。总的时间复杂度$$O(P log N)$$。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define TR(x) printf(#x"=%d
    ", x)
    const int MAXN=100005;
    int f[MAXN];
    int p[15], k[15], pk[15], s[15], phi[15], np;
    int mpow(int a,int b,int m){int r=1;for(;b;b>>=1,a=(ll)a*a%m)if(b&1)r=(ll)r*a%m;return r;}
    int calc(int n, int x){
    	if(!n) return 1;
    	int q=pk[x], t=n/q, r=1;
    	if(t){
    		for(int i=1; i<q; ++i) if(i%p[x]) r=(ll)r*i%q;
    		r=mpow(r,t,q);
    	}
    	for(int i=n%q; i>=1; --i) if(i%p[x]) r=(ll)r*i%q;
    	return (ll)r*calc(n/p[x], x)%pk[x];
    }
    int cntp(int n, int p){
    	int r=0;
    	while(n) r+=(n/=p);
    	return r;
    }
    int main(){
    	int n, m, P, ans=0;
    	scanf("%d%d%d", &n, &m, &P);
    	for(int i=2, tp=P; i<=tp; ++i) if(tp%i==0){
    		p[np]=i; pk[np]=1;
    		while(tp%i==0) tp/=i, k[np]++, pk[np]*=i;
    		phi[np]=pk[np]/i*(i-1); np++;
    	}
    	for(int i=0; i<np; ++i){
    		int t=cntp(n,p[i])-cntp(m,p[i])-cntp(n-m,p[i]);
    		s[i]=mpow(p[i],t,pk[i]);
    		s[i]=(ll)s[i]*calc(n,i)%pk[i];
    		s[i]=(ll)s[i]*mpow(calc(m,i),phi[i]-1,pk[i])%pk[i];
    		s[i]=(ll)s[i]*mpow(calc(n-m,i),phi[i]-1,pk[i])%pk[i];
    	}
    	for(int i=0; i<np; ++i){
    		ans=(ans+(ll)s[i]*(P/pk[i])%P*mpow(P/pk[i],phi[i]-1,pk[i])%P)%P;
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    CodeForces 834C
    HDU 6048
    HDU 6052
    HDU 6036
    HDU 6042
    HDU 2614 Beat(DFS)
    UESTC 1272 Final Pan's prime numbers(乱搞)
    HDU 2064 汉诺塔III(递归)
    HDU 2102 A计划(DFS)
    HDU 1069 I Think I Need a Houseboat(模拟)
  • 原文地址:https://www.cnblogs.com/will7101/p/6594521.html
Copyright © 2011-2022 走看看