• 【模拟7.22】visit(卢卡斯定理&&中国剩余定理)


    如此显然的组合数我把它当DP做,我真是。。。。

    因为起点终点已经确定,我们发现如果我们确定了一个方向的步数其他方向也就确定了

    组合数做法1:

    设向右走了a步,然后向左走了b=a-n步,设向上为c,向下为d;

    c+d=t-a-b; c-d=m;

    求出c=(t+n+m-i-i)/2;if(c%2)continue;

    (因为如果c不能整除2表示向右多走的步数无法走回)

    组合数做法2:

    参考nc神犇的做法

    首先设水平方向一共走了i步,所以(i-n)/2为水平方向上返回的步数,

    竖直方向上步数t-i,中同理返回的是(t-i-m)/2;

    式子C(t,i)*C(i,(i-n)/2)*C(t-i,(t-i-m)/2)

    (因为竖直方向+水平方向步数=t,所以不用乘C(t-i,t-i))

    至于卢卡斯和中国剩余定理(随便总结的)

    我们发现数据为多个质数乘积,显然可以用中国剩余定理求解,当然要提前分解质因数

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<string>
      5 #include<algorithm>
      6 #include<cmath>
      7 #include<stack>
      8 #include<vector>
      9 #include<queue>
     10 #define MAXN 100001
     11 #define ps push_back
     12 #define ll long long
     13 using namespace std;
     14 vector<int>su;ll jie[MAXN];
     15 void fen(int x)
     16 {
     17    for(int i=2;i<=sqrt(x);++i)
     18    {
     19        if(x%i==0)
     20        {
     21            while(x%i==0)
     22            {
     23                x/=i;
     24            }
     25            su.ps(i);
     26        }
     27    }
     28    if(x!=1)
     29    {
     30           su.ps(x);
     31    }
     32 }
     33 ll pow(ll x,ll y,ll mod)
     34 {
     35     ll ans=1;
     36     if(y==0)return 1;
     37     while(y)
     38     {
     39        if(y&1)ans=ans*x%mod;
     40        x=x*x%mod;
     41        y>>=1;
     42     }
     43     return ans%mod;
     44 }
     45 ll C(ll x,ll y,ll mod)
     46 {
     47     if(y>x)return 0;
     48     if(y==0)return 1;
     49     return jie[x]*pow(jie[y]*jie[x-y]%mod,mod-2,mod)%mod;
     50 }
     51 ll lus(ll x,ll y,ll mod)
     52 {
     53    if(y>x)return 0;
     54    if(y==0)return 1;
     55    return lus(x/mod,y/mod,mod)*C(x%mod,y%mod,mod)%mod;
     56 }
     57 ll M[MAXN],ans[MAXN];
     58 void exgcd(ll a,ll b,ll &x,ll &y)
     59 {
     60    if(b==0){
     61       x=1;y=0;return ;
     62    }
     63    exgcd(b,a%b,x,y);
     64    ll z=x;x=y;y=z-(a/b)*y;
     65    return ;
     66 }
     67 ll sum;ll len=1;
     68 void CRT()
     69 {
     70    for(ll i=0;i<su.size();++i)
     71    {
     72       len*=su[i];    
     73       //printf("%lld
    ",len);  
     74    }
     75    for(ll i=0;i<su.size();++i)
     76    {
     77       M[i]=len/su[i];
     78    }
     79    for(ll i=0;i<su.size();++i)
     80    {
     81         ll x,y;
     82         exgcd(M[i],su[i],x,y);
     83         x=(x+su[i])%su[i];
     84         sum=(sum+ans[i]*M[i]*x)%len;
     85         //printf("sum=%lld ans=%lld M=%lld x=%lld
    ",sum,ans[i],M[i],x);
     86    }
     87    printf("%lld
    ",sum);
     88 }
     89 ll t;
     90 void fir(ll mod)
     91 {
     92     for(ll i=1;i<=min(mod,t);++i)
     93     {
     94         jie[i]=(jie[i-1]*i)%mod;
     95     }
     96 }
     97 ll MOD,n,m;
     98 int main()
     99 {
    100       scanf("%lld%lld",&t,&MOD);
    101       scanf("%lld%lld",&n,&m);
    102       if(n<0)n=-n;
    103       if(m<0)m=-m;
    104       jie[0]=1;    
    105       fen(MOD);
    106       for(ll k=0;k<su.size();++k)
    107       {
    108           fir(su[k]);
    109           ll mod=su[k];
    110           //printf("mod=%lld
    ",mod);
    111           for(ll i=n;i<=t-m;++i)
    112           {     
    113             ll a=i;
    114             ll b=i-n;
    115             ll c=(t+n+m-i-i);
    116             if(c%2!=0)continue;c/=2ll;
    117             ll d=t-a-b-c;
    118             ans[k]=(ans[k]+lus(t,a,mod)*lus(t-a,b,mod)%mod*lus(t-a-b,c,mod)%mod+mod)%mod;
    119           }
    120      }
    121      CRT();
    122 }
    View Code
  • 相关阅读:
    Mysql 之根据经纬度按距离排序
    Python的列表和元组
    go实现堆排序、快速排序、桶排序算法
    微信Hook劫获protobuf数据
    手机号批量查询微信昵称/网名/名称
    保存整个网页的内容
    天地图官网引入文件
    Postman-动态传参
    JAVA FileOutputStream与BufferedOutputStream的区别
    JAVA中sleep()和wait()的区别
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11231016.html
Copyright © 2020-2023  润新知