zoukankan      html  css  js  c++  java
  • 【2019.8.15 慈溪模拟赛 T2】组合数(binom)(卢卡斯定理+高维前缀和)

    卢卡斯定理

    题目中说到(p)是质数。

    而此时要求组合数向质数取模的结果,就可以用卢卡斯定理:

    [C_x^y=C_{x div p}^{y div p}cdot C_{x mod p}^{y mod p} ]

    也就是说,我们可以把(x)(y)转化成两个(p)进制数,然后每一位分别求组合数后再乘起来。

    所以问题来了,什么时候一个组合数的值模(p)(0)

    由于它是质数,所以对于一个组合数(C_a^b),当且仅当(a<b)时它的值才会为(0)

    也就是说,对于两个数(x,y),只要(y)(p)进制下有一位的值比(x)这一位大,(C_x^y=0)

    高维前缀和

    考虑先容斥。

    我们用总方案数((n^2))减去组合数不为(0)的组数,就是答案。

    (C_x^y)不为(0),当且仅当(y)(p)进制下每一位的值都小于等于(x)这一位。

    是不是想到了高维偏序。。。

    然后,这道题就变成裸的高维前缀和了。

    如果你不知道高维前缀和,可以去看看我的这篇博客:浅谈高维前缀和

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1000000
    #define LL long long
    #define Qinv(x) Qpow(x,X-2)
    using namespace std;
    int n,X,a[N+5],s[N+5];
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define tn (x<<3)+(x<<1)
    		#define D isdigit(c=tc())
    		char c,*A,*B,FI[FS];
    	public:
    		I FastIO() {A=B=FI;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
    }F;
    int main()
    {
    	freopen("binom.in","r",stdin),freopen("binom.out","w",stdout);
    	RI i;LL p,ans=0;for(F.read(n),F.read(X),i=1;i<=n;++i) F.read(a[i]),++s[a[i]];//读入
    	for(p=1;p<=N;p*=X) for(i=0;i<=N;++i) (i/p)%X&&(s[i]+=s[i-p]);//高维前缀和
    	for(i=1;i<=n;++i) ans+=n-s[a[i]];return printf("%lld",ans),0;//容斥求答案
    }
    
  • 相关阅读:
    spring cloud项目搭建
    获取iframe的window对象
    数学杂谈 #7
    [AGC023D] Go Home
    JOISC 2021 部分题解
    [NOI2017]泳池
    [NOI2016] 循环之美
    [NOI2016] 优秀的拆分
    [LG P3676]小清新数据结构题
    [ARC113F]Social Distance
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Contest20190815T2.html
Copyright © 2011-2022 走看看