一、题目链接

  http://acm.hdu.edu.cn/showproblem.php?pid=5226

二、题意

  给一个大矩阵,其中,$a[i][j] = C_i^j$。输入5个参数,$x_1, y_1, x_2, y_2, p$,输出:以$x_1, y_1$为左上角,$x_2, y_2$为右下角的子矩阵中所有值累加和$\% p$的结果。

三、思路

  看完题意后,想了一会儿,实在想不到如何降低复杂度。于是,就去看题解了。(PS:想了大概20分钟左右后还是没思路可以果断去看题解了。既然不知道方法,想再久也没用,最后还是要看题解的)。所以,我这篇文章,只是对知识点的整理和总结,而不是原创思路的分享。

  对于组合数来说,有$C_n^m = C_{n-1}^{m-1} + C_{n-1}^m$。看个表。

  这个表大家都很熟悉,就是组合数的表,因为$C_n^m = C_{n-1}^{m-1} + C_{n-1}^m$,所以,\[C_{n+1}^m = C_n^{m-1} + C_n^m = C_n^{m-1} + C_{n-1}^{m-1} + C_{n-1}^m = C_n^{m-1} + C_{n-1}^{m-1} + C_{n-2}^{m-1}+C_{n-2}^{m}\],由上述递推式可以发现,要计算$\sum\limits_{i=x_1}^{x_2}a[i][y]$,只要计算$C_{x_2+1}^{y+1} - C_{x_1}^{y+1}$即可。而且,更巧的是,对于对角线上的值,该式子也成立。

  那么,有了上述推论,复杂度就降了一个维度了。从$y_1$枚举每一列到$y_2$,对每一列使用上述公式求值即可。

  在做组合数求模$C_n^m\ \%\ p$的过程中,因为有可能存在$p \le \frac{n}{m}$的样例,那么就会出现这么一种情况:$p | n!, p | m!, p | (n-m)!$,如果使用n的阶乘*m的阶乘的逆元*(n-m)的阶乘的逆元来计算,返回值会是0。而实际上,真正的返回值并不一定是0。举个例子:

\[C_6^2 = \frac{6!}{2! * 4!} = \frac{720}{2 * 24} = 15\]

\[C_6^2\ \%\ 2 = 15\ \%\ 2 = 1 \ne 0 \]

  所以,直接做计算组合数求模是不行的(也就是说,如果存在上述情况,用扩展欧几里得算法、费马小定理算法都不行了),要用lucas定理才行。

  另外,还要注意的一点是,在初始化阶乘数组的时候,千万别忘了初始化阶乘逆元数组的第0个元素。即:inv[0] = 1。

四、源代码

  

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100100
using namespace std;
typedef long long LL;
LL facts[MAXN], inv0[MAXN], x1, x2, y1, y2, p;

LL qpow(LL a, LL x) {
    LL res = ;
    ) {
        )res = (res * a) % p;
        a = (a * a) % p;
        x >>= ;
    }
    return res;
}

void init() {
    facts[] = inv0[] = ;
    ; i < MAXN; ++i) {
        facts[i] = (facts[i - ] * i) % p;
        inv0[i] = qpow(facts[i], p - );
    }
}

LL C(LL n, LL m) {
    ;
    );
    )return n % p;
    return facts[n] * inv0[m] % p * inv0[n - m] % p;
}

LL lucas(LL n, LL m) {
    if(n < p && m < p)return C(n, m);
    else return lucas(n / p, m / p) * lucas(n % p, m % p) % p;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
#endif
    while(~scanf("%I64d %I64d %I64d %I64d %I64d", &x1, &y1, &x2, &y2, &p)) {
        init();
        LL ans = ;
        ;i <= y2 + ;++i)ans = (ans + lucas(x2 + , i) - lucas(x1, i) + p) % p;
        printf("%I64d\n", ans);
    }
    ;
}

HDU-5226 Tom and matrix(组合数求模)的更多相关文章

  1. 组合数(Lucas定理) + 快速幂 --- HDU 5226 Tom and matrix

    Tom and matrix Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=5226 Mean: 题意很简单,略. analy ...

  2. HDU 5226 Tom and matrix(组合数学+Lucas定理)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5226 题意:给一个矩阵a,a[i][j] = C(i,j)(i>=j) or 0(i < ...

  3. sdut2164Binomial Coeffcients(组合数求模)

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2164 贴一篇写组合数求mod比较好的帖子 这里 ...

  4. HDU-3944 DP?(组合数求模)

    一.题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3944 二.题意 给一个巨大的杨辉三角,采用类似DP入门题“数字三角形”的方式求从顶点$(0, 0) ...

  5. 【转载】【转自AekdyCoin的组合数取模】

    本篇文章主要介绍了"[组合数求模] 转自AekdyCoin",主要涉及到[组合数求模] 转自AekdyCoin方面的内容,对于[组合数求模] 转自AekdyCoin感兴趣的同学可以 ...

  6. 【转】AC神组合数取模大全

    貌似少了几张图片,不过没有图片也没什么关系的感觉. 最后的究极篇也想出来了,但是貌似找不到题目,好尴尬.. 这个表示的是从n个元素中选取m个元素的方案数. (PS.组合数求模似乎只用在信息学竞赛和 A ...

  7. 排列组合+组合数取模 HDU 5894

    // 排列组合+组合数取模 HDU 5894 // 题意:n个座位不同,m个人去坐(人是一样的),每个人之间至少相隔k个座位问方案数 // 思路: // 定好m个人 相邻人之间k个座位 剩下就剩n-( ...

  8. hdu 3944 DP? 组合数取模(Lucas定理+预处理+帕斯卡公式优化)

    DP? Problem Description Figure 1 shows the Yang Hui Triangle. We number the row from top to bottom 0 ...

  9. hdu 2065 "红色病毒"问题(快速幂求模)

    n=1  --> ans = 2 = 1*2 = 2^0(2^0+1) n=2  -->  ans = 6 = 2*3 = 2^1(2^1+1) n=3  -->  ans = 20 ...

随机推荐

  1. Kolakoski数列

    2018-04-16 15:40:16 Kolakoski序列是一个仅由1和2组成的无限数列,是一种通过“自描述”来定义的数列.他在整数数列大全网站上排名第二位,足见该数列在组合数学界中的重要性. K ...

  2. django使用bootstrap快速美化 admin后台

    使用django-admin-bootstrappe快速美化后台 两步: 1.pip install django-admin-bootstrapped  安装应用 2.在setting.py里面添加 ...

  3. echart3 湖北地图及如何创建其他省份地图

    刚刚收到一封园友求助echart湖北地图的邮件,现在将湖北地图的所有代码贴到这里,希望可以帮助到更多朋友. 1.首先你得到echarts官网下载js,很多人说找不到,可以到我的git下载(https: ...

  4. 函数响应式编程RxJava

    RxJava 到底是什么 一个词:异步. RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynchronous and event- ...

  5. Http协议——Header说明

    下图是我用IE的开发人员工具截取的一个Http Request请求的Header. 下图是我用IE的开发人员工具截取的一个Http Response的Header. header常用指令 header ...

  6. C++ readdir、readdir_r函数

    readdir, readdir_r - 读一个目录 readdir函数: struct dirent *readdir(DIR *dirp); The  data  returned by read ...

  7. 《DSP using MATLAB》示例Example 10.4

    代码: %% ------------------------------------------------------------------------ %% Output Info about ...

  8. Hibernate环境搭建+struts整合

    说明:本文档,是和struts2+hibernate的整合示例. lib下还有struts2的jar包,本示例没有显示.struts2的搭建参考struts2的环境搭建 一下载hibernate的ja ...

  9. 使用xUnit为.net core程序进行单元测试(2)

    第一部分: http://www.cnblogs.com/cgzl/p/8283610.html 下面有一点点内容是重叠的.... String Assert 测试string是否相等: [Fact] ...

  10. QQ空间点赞代码

    jQuery("a.qz_like_btn_v3[data-clicklog='like']").each(function(index,item){ console.log(it ...