一、题目链接

  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. UVa 10375 选择与除法(唯一分解定理)

    https://vjudge.net/problem/UVA-10375 题意: 输入整数p,q,r,s,计算C(p,q)/C(r,s). 思路: 先打个素数表,然后用一个数组e来保存每个素数所对应的 ...

  2. shell 判断文件是否是可执行文件

    测试变量指定的文件是否存在且是可执行文件.如果存在且是可执行文件,则执行该文件,否则通过chmod命令赋予该文件可执行权限. //test.sh #!/bin/bash echo "ente ...

  3. python字典格式化输出

    #!/usr/bin/env python#coding=utf-8#__author__='David Chung' dict1={'pid':1375,'type':'cpu','resource ...

  4. Spring MVC 实现跨域资源 CORS 请求

    说到 AJAX 跨域,很多人最先想到的是 JSONP.的确,JSONP 我们已经十分熟悉,也使用了多年,从本质上讲,JSONP 的原理是给页面注入一个 <script>,把远程 JavaS ...

  5. URAL 1106 Two Teams (DFS)

    题意 小组里有N个人,每个人都有一个或多个朋友在小组里.将小组分成两个队伍,每个队伍的任意一个成员都有至少一个朋友在另一个队伍. 思路 一开始觉得和前几天做过的一道2-sat(每个队伍任意两个成员都必 ...

  6. 【hive】cube和rollup函数

    cube 数据立方体(Data Cube),是多维模型的一个形象的说法.(关于多维模型这里不讲述,在数据仓库设计过程中还挺重要的,有兴趣自行查阅) 立方体其本身只有三维,但多维模型不仅限于三维模型,可 ...

  7. 044——VUE中组件之使用内容分发slot构建bootstrap面板panel

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Cobbler自动化安装

    # Cobbler自动化安装 [Cobbler官网](http://cobbler.github.io) ![](/Users/wanyongzhen/Library/Containers/com.t ...

  9. 关于CMD中延迟环境变量嵌套的实现方法

    在我昨天做的一个bat中(自动按日期重命名文件名)涉及到这方面的问题 以前涉及到这里时就想别的办法替代过去,今天好好扒出来说说: 实现变量嵌套的2种方法: 1,使用call实现变量嵌套 变量嵌套:即在 ...

  10. 【LeetCode 222_完全二叉树_遍历】Count Complete Tree Nodes

    解法一:递归 int countNodes(TreeNode* root) { if (root == NULL) ; TreeNode *pLeft = root->left; TreeNod ...