一、题目链接

  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. python第三方库PIL安装的各种坑

    PIL python的图像处理库,pycharm安装屡次失败,始终报错 果断换依旧报错,查遍所有博客, 有给pip加参数的,pip install PIL --allow-external PIL - ...

  2. Codeforces Round #278 (Div. 2) D. Strip 线段树优化dp

    D. Strip time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...

  3. DDMS

    DDMS 的全称是Dalvik Debug Monitor Service,是 Android 开发环境中的Dalvik虚拟机调试监控服务

  4. 反射中的 Class.forName() 与 ClassLoader.loadClass() 的区别

    在Java中,类加载器把一个类加载进Java虚拟机中,要经过三个步骤来完成:加载.链接和初始化,其中链接又可以分成验证.准备和解析三步,除了解析外,其它步骤是严格按照顺序完成的,各个步骤的主要工作如下 ...

  5. Android中的代理模式

    代理的概念:为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代.代理类负责请求的预处理.过滤.将请求分派给委托类处 ...

  6. 关闭pm2

    先查找ID pm2 status 然后 pm2 stop id pm2 delete id

  7. PHP如何安装扩展

    PHP如何安装扩展 一.总结 一句话总结:兩步: dll php.ini a.下载好扩展的dll,放入指定文件夹下 b.在php.ini配置文件中声明插件 1.什么是php扩展? php核心 不支持 ...

  8. 第108天:Ajax中XMLHttpRequest详解

    在Ajax应用程序中,XmlHttpRequest对象负责将用户信息以异步通信地发送到服务器端,并接收服务器返回的响应信息和数据. XMLHttpRequest可以提供不重新加载页面的情况下更新网页, ...

  9. Arrays.copyof(···)与System.arraycopy(···)区别

    首先观察先System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)的声明: public stati ...

  10. prim和kruskal比较

    推荐:http://squirrelrao.iteye.com/blog/1044867  http://www.cnblogs.com/xwdreamer/archive/2011/06/16/22 ...