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;
    }
    
  • 相关阅读:
    第二次作业循环语句
    c语言01次作业分支,顺序结构
    PAT 1027. Colors in Mars
    PAT 1026 Table Tennis
    PAT 1035 Password
    PAT 1038. Recover the Smallest Number
    PAT 1028 List Sorting (25)
    PAT 1041 Be Unique (20)
    PAT 1025 PAT Ranking
    1037. Magic Coupon
  • 原文地址:https://www.cnblogs.com/will7101/p/6594521.html
Copyright © 2011-2022 走看看