zoukankan      html  css  js  c++  java
  • visit 组合数取模

      题面依旧保密。。。。

      我们可以知道,这个题的不一样之处在于在网格中的步数可能远远多于需要,那么我们应该怎么做呢?考场上的思路是:首先选出来n+m步让我能走到终点,然后在去找多余的步数。然后就不会了,算重一大堆。。考后听skyh讲题的时候发现其实和最基础的方法类似,这个题的基础版是$T=n+m$,那么方案肯定是$C_{n+m}^n$,它的思想是一定走n+m步,选n步向上走,剩下向右走,一开始还纠结为什么不是,$C_{n+m}^n*C_{n+m}^m$,其实最一开始应该是$C_{n+m}^n*C_{m}^m$。那么继续这个思路,在我们T步的时候,什么时候是确定的?发现如果T-(n+m)是奇数,那么显然是死掉的。然后考虑选步,和之前一样,在观察的时候发现当上下方向的步数确定的时候,左右方向也确定,因为不能斜着走,那么可以得到,当枚举上下方向步数,再选出向上步数,剩下向下走,左右也一样。

      于是我们就愉快的得到了$sumlimits_{k=n,k+=2}^{T-m}C_{T}^{k}*C_{k}^{(k-n)/2}*C_{T-k}^{(T-k-m)/2}$.上下左右一定得走够n和m,那么就有k的范围,因为奇数一定走不到(多走偶数次才相当于没走),k一定是+2变换的,这样能保证k-n一定是偶数,k-n是上下方向上多余的步数,一定是走过去又走回来,除以2就是向下走的。然后左右同理,值得一提的就是在左右走的时候,T-k-m是左右走的废步,它也应该是偶数,证明很容易,k和n的奇偶性相同,那么T-k-m和T-n-m奇偶性相同,T-n-m一定是奇数已经死了,那这个肯定是偶数。于是这个题就愉快的解决了,然后看到输入你又会点进来,没错,模非质数。。。

      当会exlucas大神已经可以去码了,还有一个蒟蒻做法,毕竟这只是个NOIP模拟,题目给的数也不是随意的,它是一个所谓的什么square-free-number,就是质因数的最高次只有一次,那这完全可以用unexlucas。。。也就是lucas+CRT解决。

      设答案为ans,将模数分解质因数,那么就可以得到p1,p2......,我们求出ans对每一个p的余数,最终用中国剩余定理合并就知道了ans的最小值即ans%mod

      

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int N=1000020;
    int p[N],w[N],tt;
    int fac[N],inv[N];
    long long rd()
    {
        long long s=0;
        char cc=getchar();
        while(cc<'0'||cc>'9') cc=getchar();
        while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar();
        return s;
    }
    const long long t=rd(),mod=rd(),n=rd(),m=rd();
    inline long long qpow(int a,int k,int p)
    {
        long long ans=1;
        for(;k;k>>=1,a=1ll*a*a%p) if(k&1) ans=1ll*ans*a%p;
        return ans;
    }
    inline long long C(int n,int m,int p)
    {
        if(n<m) return 0;
        return 1ll*fac[n]*inv[m]%p*inv[n-m]%p;
    }
    inline void cut(int n)
    {
        for(register int i=2;1ll*i*i<=n;i++)
            if(n%i==0)
                p[++tt]=i,n/=i;
        if(n>1)p[++tt]=n;
        //return tt==1;
    }
    long long lucas(int n,int m,int p)
    {
        if(m==0) return 1;
        return C(n%p,m%p,p)*lucas(n/p,m/p,p)%p;
    }
    inline long long crt()
    {
        long long ans=0;
        for(register int i=1;i<=tt;i++) ans=(ans+(mod/p[i])*qpow(mod/p[i],p[i]-2,p[i])%mod*w[i]%mod)%mod;
        return ans;
    }
    void get_fac(int p)
    {
        register int mm=min(1ll*p-1,t);
        fac[0]=1;
        for(register int i=1;i<=mm;i++) fac[i]=1ll*fac[i-1]*i%p;
        inv[mm]=qpow(fac[mm],p-2,p);
        for(register int i=mm;i>0;i--) inv[i-1]=1ll*inv[i]*i%p;
    }
    int main()
    {
        cut(mod);
        for(register int i=1;i<=tt;i++)
        {
            get_fac(p[i]);
            for(register int k=n;k<=t-m;k+=2)
                w[i]=(w[i]+lucas(t,k,p[i])*lucas(k,(k-n)/2,p[i])%p[i]*lucas(t-k,(t-k-m)/2,p[i])%p[i])%p[i];
        }
        printf("%lld
    ",crt());
    }
    View Code
    Zeit und Raum trennen dich und mich.时空将你我分开。
  • 相关阅读:
    spring boot整合quartz存储到数据库
    java多线程定时器和java判断一个时间是否在时间区间内和用正则表达式获取String字符串之间的数据
    maven项目通过java加载mqtt存储到mysql数据库,实现发布和接收
    java往MongDB导入大量数据
    SSH面试题收藏
    Spring面试题
    Hibernate面试题收藏
    Spring MVC
    浅谈 Struts2 面试题收藏
    JSP 新闻发布会
  • 原文地址:https://www.cnblogs.com/starsing/p/11235539.html
Copyright © 2011-2022 走看看