2017年12月10日训练笔记

43 篇文章 0 订阅
18 篇文章 0 订阅

      这星期打的两场比赛还是只能做一做水题,就今天比赛的问题还是没想清楚就敲代码,反而简单的题目不能快速做出来,还有今天组合数学快结束了,组合数学用的多的就是组合数的各种等价变换、在对组合数求余时的Lucas定理、求组合数时的除法求逆元、这两天做的题目都是有关容斥定理的,其实容斥定理也只是一个思想,倒是也有一定套路可寻,容斥定理一般可用位运算和dfs来实现,但我在会用位运算了之后就不想再考虑dfs了,但是位运算效率有限比如大多数容斥定理用到的就是用容斥定理求区间[1,r]内与n互质的数的个数,然后将这个问题转化为求解区间内与n不互素的数的个数,再用区间长度减之。用容斥定理来说就是:先将n分解质因数,找出区间中可以被每个质因子整除的数的个数(即质因子倍数的个数--r/p[i]),减去可以被其任意两个质因子整除的数的个数,加上可以被其任意三个质因子整除的数的个数......用位运算实现如下

 

ll solve(ll r)   //求在区间[l,r]中与n互素的数的个数
{  
    ll sum=0;  
    for(ll msk=1;msk<(1ll<<len);msk++) //(1<<len)是一个长为len的二进制,通过msk从1到(1<<len)循环可以枚举这个二进制的每一种排列情况来表示每一种素因子的组合情况  
    {  
        ll mult=1,bits=0;  
        for(ll i=0;i<len;i++)   
        {  
            if(msk&(1ll<<i)) //判断p[i]素因子是否在当前排列中,  
            {  
                ++bits;  
                mult*=p[i];  //p[i]是将n分解质因子的数组
            }  
        }  
        //比如有只有p1,p2在排列中,那么这一项为-r/(p1*p2),若只有p1那么+r/p1  
        ll cur=r/mult;  
        if(bits&1)  
            sum+=cur;  
        else  
            sum-=cur;  
    }  
    return sum;  
}  

这里比如质因子有len个,msk代表一个长度为len的二进制串,用来表示当前组合有哪些质因子,比如len=6,msk为一个长度为6的二进制串,比如msk=000001,这里1表示选中,0表示未选中,说明当前组合为p[0],即区间中可以被质因子p[0]整除的数的个数,再比如msk=100110,那么说明p[1],p[2],p[5]是选中的,即区间中可以被质因子p[1]、p[2]、p[5]整除的数的个数(即三者最小公倍数的所有倍数),而这是怎么实现的呢,通过内层循环每个质因子,如果(msk&(1<<i))==1那么确定p[i]被选中,通过msk从000000到111111的循环找出所有情况。

 

当然一般一个数的质因子也不会太多。但对于其他题目,这里很明显当len较大的时候这样是很慢的。
 

 

Lucas定理:Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p) ,表示为组合数:C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p

 

ll Lucas(ll n,ll m)  
{  
    if(m==0)  
        return 1;  
    return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod;  
}  

 

题目:hdu - 4349 - Xiao Ming's Hope - (Lucs定理)

 

除法求逆元:即可以理解为公式b^(p-2)==(1/b) (mod p),应用起来就是(a/b)%mod=(a*pow_mod(b,mod-2)%mod)%mod;

 

ll C(ll n,ll m)  
{  
    if(n<m)  
        return 0;  
    ll ans=1;  
    for(ll i=1;i<=m;i++)  
    {  
        ll a=n-m+i;  
        ll b=i;  
        //本来有ans=ans*(a/b),但是除法不满足取余,利用b^(p-2)==(1/b) (mod p)  
        ans=ans*(a*pow_mod(b,mod-2)%mod)%mod;  
    }  
    return ans;  
}  

 

题目:HDU - 5698 - 瞬间移动 - (除法求逆元,Lucas定理,组合数求路径)

 

求1~n的4次方之和余mod

 

ll sum(ll x) //求1~n的4次方之和余mod  
{  
    ll t1 = (x * (x + 1) % mod) * ((2 * x + 1) % mod);  
    ll t2 = ((3 * x * x + 3 * x - 1) % mod) * pow_mod(30ll, mod - 2);  
    return ((t1 % mod) * (t2 % mod)) % mod;  
}  

 

 

 

用到的等价变化有:C(n,k)=C(n,k-1)*(n-k+1)/k,c[i][j]=c[i-1][j]+c[i-1][j-1]; 

 

 

C(m,0)*C(n,0)+C(m,1)*C(n,1)+C(m,2)*C(n,2)+...+C(m,n)*C(n,n)=C(m+n,m)

 

还有PPT上求路径的问题也很经典,即从(0,0)点出发沿x轴或y轴的正方向每步走一个单位,最终走到(m,n)点,有多少
条路径?为C(m+n,n),那么从(a,b)到(c,d)的非降路径数为C(c-a+d-b,c-a),

 

再则在上例的基础上若设m<n,求(0,1)点到(m,n)点不接触对角线x=y的非降路径的数目

(1-(m/n))*C(m+n-1,m)

若设m<n,求(0,1)点到(m,n)点不穿过但课接触对角线x=y的非降路径的数目

((n+1-m)/(n+1))*C(m+n,m)

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值