• 暑假集训Day1 L (Lucas+容斥原理)


    题目链接在本地……

    这题题意就是一个二维图,按象棋中马的走位从左上走到右下,中间有一些点不能到达,问有多少条路径。

    可以很明显的想到是一个容斥的问题,但是如此众多的点,放在一起容斥属实非常复杂。在这种情况下,一般都要想到由简入繁:想到一个个的把点加进去看。

    现将点都排一遍序,从左上到右下,开一个数组f[i]记录到当前点的路径上,不经过前面任何一个不能到的点的路径条数。

    那么对于一个新的点x,结果 f[x] 就是从左上角到 x 的路径数减去所有 x 前面的点 j 到 x 的路径条数乘上 f[j]。因为 f 中存放的路径是干净的,不经过任何先前的不能到的点,所以这个不会减去重复的路径。这种容斥的思想值得学习。

    另一个值得学习的就是遇到很大的组合数时,要想到Lucas定理,这个可以快速的计算longlong范围的组合数。所以要顺便学一下线性求阶乘逆元的方法。要学习的东西有很多!!

     1 #include "bits/stdc++.h"
     2 using namespace std;
     3 typedef long long LL;
     4 const int MAX=115;
     5 const int MOD=110119;
     6 LL t;
     7 LL n,m,r,f[MAX];
     8 LL fac[MOD],inv[MOD],facinv[MOD];
     9 struct Node{
    10     LL x,y;
    11     bool operator < (const Node &tt) const{
    12         if (x!=tt.x) return x<tt.x;
    13         return y<tt.y;
    14     }
    15 }a[MAX];
    16 void init(){
    17     LL i,j;
    18     memset(fac,0,sizeof(fac));
    19     memset(inv,0,sizeof(inv));
    20     memset(facinv,0,sizeof(facinv));
    21     fac[0]=fac[1]=inv[1]=facinv[0]=facinv[1]=1;
    22     for (i=2;i<MOD;i++){
    23         fac[i]=fac[i-1]*i%MOD;
    24         inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;
    25         facinv[i]=facinv[i-1]*inv[i]%MOD;
    26     }
    27 }
    28 LL C(LL n, LL m){
    29     if(n<0 || m<0 || m>n) return 0;
    30     return fac[n] * facinv[m] % MOD * facinv[n - m] % MOD;
    31 }
    32 
    33 LL Lucas(LL n, LL m){
    34     if(n<0 || m<0 || m>n) return 0;
    35     LL res = 1;
    36     while(n || m) {
    37         res = res * C(n % MOD, m % MOD) % MOD;
    38         n/=MOD;
    39         m/=MOD;
    40     }
    41     return res;
    42 }
    43 int main(){
    44 //    freopen ("l.in","r",stdin);
    45 //    freopen ("l.out","w",stdout);
    46     LL i,j,zt1,zt2,step;
    47     scanf("%lld",&t);
    48     init();
    49     while (t--){
    50         scanf("%lld%lld%lld",&n,&m,&r);
    51         for (i=1;i<=r;i++)
    52             scanf("%lld%lld",&a[i].x,&a[i].y);
    53         a[r+1].x=a[r+1].y=1;
    54         a[r+2].x=n,a[r+2].y=m;
    55         sort(a+1,a+r+3);
    56         memset(f,0,sizeof(f));
    57         f[1]=-1+MOD;
    58         for (i=2;i<=r+2;i++){
    59             for (j=1;j<i;j++){
    60                 if (a[i].x < a[j].x || a[i].y < a[j].y || (a[i].x-a[j].x+a[i].y-a[j].y)%3 != 0 ) continue;
    61                 step=(a[i].x-a[j].x+a[i].y-a[j].y)/3;
    62                 zt1=a[i].x-a[j].x-step;
    63                 zt2=a[i].y-a[j].y-step;
    64                 f[i]=(f[i]+MOD-f[j]*Lucas(zt1+zt2,zt1)%MOD)%MOD;
    65             }
    66         }
    67         printf("%lld\n",f[r+2]);
    68     }
    69     return 0;
    70 }
  • 相关阅读:
    秒杀项目之——通过令牌发放机制,控制秒杀大闸以及队列泄洪
    Guava的使用
    秒杀项目之细节随笔记录————
    redis搭建集群
    redis内存满了怎么办?
    多个电脑上免密登陆命令、scp远程拷贝、修改文件的用户和组
    克隆完虚拟机后修改网卡,修改静态IP
    redis基本操作和 过期时间设置以及持久化方案
    linux操作系统安装运行Redis
    云服务器以及linux操作系统打开防火墙,在墙上开一个小口
  • 原文地址:https://www.cnblogs.com/keximeiruguo/p/16448322.html
Copyright © 2020-2023  润新知