zoukankan      html  css  js  c++  java
  • [入门OJ3876]怎样学习哲学

    题目大意:
      有一个$n imes m(n,mleq 10^9)$的网格图,从一个点可以到下一行中列数比它大的点。有$k(kleq 2000)$个点是不能走的,问从第$1$行到第$n$行共有几种方案。

    思路:
      动态规划求出以点$i$为终点的方案数,直接$O(nm)$推显然会超时,因此我们$O(k)$可以对于每个障碍点求出组合数。组合数可以用Lucas定理求。
      Lucas定理:$inom{n}{m}mod p=inom{lfloorfrac{n}{p} floor}{lfloorfrac{m}{p} floor}inom{nmod p}{mmod p}mod p$。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<vector>
     4 #include<algorithm>
     5 typedef long long int64;
     6 inline int getint() {
     7     register char ch;
     8     while(!isdigit(ch=getchar()));
     9     register int x=ch^'0';
    10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    11     return x;
    12 }
    13 const int mod=1000003,K=2001;
    14 int fact[mod],factinv[mod],f[K];
    15 std::pair<int,int> v[K];
    16 void exgcd(const int &a,const int &b,int &x,int &y) {
    17     if(!b) {
    18         x=1;
    19         y=0;
    20         return;
    21     }
    22     exgcd(b,a%b,y,x);
    23     y-=a/b*x;
    24 }
    25 inline int inv(const int &x) {
    26     int ret,tmp;
    27     exgcd(x,mod,ret,tmp);
    28     return (ret%mod+mod)%mod;
    29 }
    30 int lucas(const int &n,const int &m) {
    31     if(n<m) return 0;
    32     if(n<mod&&m<mod) return (int64)fact[n]*factinv[m]%mod*factinv[n-m]%mod;
    33     return (int64)lucas(n/mod,m/mod)*lucas(n%mod,m%mod)%mod;
    34 }
    35 int main() {
    36     fact[0]=1;
    37     for(register int i=1;i<mod;i++) {
    38         fact[i]=(int64)fact[i-1]*i%mod;
    39     }
    40     factinv[mod-1]=inv(fact[mod-1]);
    41     for(register int i=mod-2;~i;i--) {
    42         factinv[i]=(int64)factinv[i+1]*(i+1)%mod;
    43     }
    44     const int n=getint(),m=getint(),k=getint();
    45     for(register int i=0;i<k;i++) {
    46         const int x=getint(),y=getint();
    47         v[i]=std::make_pair(x,y);
    48     }
    49     std::sort(&v[0],&v[k]);
    50     v[k]=std::make_pair(n+1,m+1);
    51     for(register int i=0;i<=k;i++) {
    52         f[i]=lucas(v[i].second-1,v[i].first-1);
    53         for(register int j=0;j<i;j++) {
    54             if(v[i].first<=v[j].first||v[i].second<=v[j].second) continue;
    55             f[i]=((f[i]-(int64)f[j]*lucas(v[i].second-v[j].second-1,v[i].first-v[j].first-1))%mod+mod)%mod;
    56         }
    57     }
    58     printf("%d
    ",f[k]);
    59     return 0;
    60 }
  • 相关阅读:
    Html-浅谈如何正确给table加边框
    如何在移动设备上调试html5开发的网页
    swiper嵌套小demo(移动端触摸滑动插件)
    移动端如何用swiper实现导航栏效果
    background-color:transparent
    点击按钮 发送短信验证码后60秒倒计时
    placeholder的样式设置
    linux 定时任务crontab
    laravel学习一
    centos 7安装jdk
  • 原文地址:https://www.cnblogs.com/skylee03/p/8258092.html
Copyright © 2011-2022 走看看