@hdu - 6372@ sacul
@description@
定义矩阵 \(A_i\) 是一个大小为 \(p^i*p^i\) 的矩阵,其中 \(p\) 是第 \(c\) 个素数(c 给定),且 \(A_i[x][y] = [C(x, y) \mod p > 0]\)(其中 C(x, y) 是组合数)。
行列从 0 开始计数。
再定义 \(F[i][j]\) 表示 \((A_i)^j\) 中所有元素之和。
求 \(\sum_{i=1}^n\sum_{j=1}^{k}F[i][j]\)。对 10^9 + 7 取模。
Input
第一行包含一个整数 T,然后接下来是 T 组数据:
每一组数据包含三个整数 c, n, k (0 < n ≤ 10^9, 0 < c, k ≤ 10^5)。意义如上。
Output
对于每组数据,输出一个整数表示答案。
Sample Input
1
1 1 1
Sample Output
3
@solution@
看上去这个题非常不可做,先定义了一个矩阵,然后又要求矩阵幂,然后又要把这个矩阵幂中所有元素求和,然后又要把这些矩阵求和的结果再求和。
但是你只需要找到突破口,剩下的部分就一气呵成(其实一气呵成这个词不能这么用。。。今年中考考了这玩意儿,然后做错了,所以印象深刻。。。)
怎么找突破口?你只需要把题目倒过来读注意到矩阵的定义涉及到组合数对素数取模,于是就可以牵扯出 lucas 定理。
lucas 定理是什么?其实很简单。对于 \(C(n, m) \mod p\),我们将 n, m 拆成 p 进制数的形式,即 \(n = n_0 + n_1*p^1 + ..., m = m_0 + m_1*p^1 + ...\)。
于是 lucas 定理告诉我们:\(C(n, m) = C(n_0, m_0)*C(n_1, m_1)*... \mod p\)
证明这个定理也不难,只是与这道题无关所以暂且不提。
很显然 \(C(n, m) \mod p \ge 0\),所以我们只需要判断 \(C(n, m) \mod p = 0\) 是否成立即可。
又因 \(n_i < p, m_i < p\) (因为是 p 进制嘛),所以 \(C(n_i, m_i)\) 不可能含因子 p,故我们只需要对于每一个 i 判断是否 \(C(n_i, m_i) = 0\),而前面那个等价于 \(n_i > m_i\)。
所以 \(A_i[x][y]\) 为 1 等价于在 p 进制下 x 的每一位都 ≤ y 的对应位。
现在考虑 \((A_i)^j[x][y]\) 怎么求。
先试着考虑 \((A_i)^2[x][y]\),可以发现 \((A_i)^2[x][y] = \sum_{z}A_i[x][z]*A_i[z][y]\),只有当 \(A_i[x][z], A_i[z][y]\) 都为 1 时才会产生贡献。
这有点儿像偏序的关系,因为有些传递性和偏序形成链的感觉在里面。
或者用图论的语言,如果 \(A_i[x][y] = 1\) 则 x 向 y 连边。则 \((A_i)^2[x][y]\) 则有点儿像走两步(中途可以停留在原地)从 x 到达 y 的方案数。
从而简单推广,可以得到 \((A_i)^j[x][y]\) 表示走 j 步从 x 到达 y 的方案数。
那么 F[i][j] 的含义是什么?为了计数的方便我们暂且不用图论的语言描述。
F[i][j] 表示长度为 i 的 p 进制的数字串,选出 j+1 个记为 s0, s1, ... sj,对于第 x 位(1≤x≤n)始终满足 s0[x] ≤ s1[x] ≤ ... ≤ sj[x] 的方案总数。
怎么求 F[i][j] 呢?其实也比较简单。因为每一位都是独立的,所以考虑某一位然后乘法原理乘起来即可。
我们发现如果确定了 s0[x], s1[x], ..., sj[x] 分别是哪些数,它们的顺序始终是一定的(即排序过后的顺序)。所以我们相当于是求 x1 + ... + xp = j + 1 的非负整数解的个数。经典的组合数学问题,答案为 C(j+p, j+1)。
于是 F[i][j] = C(j+p, j+1)^i。
于是 \(\sum_{i=1}^n\sum_{j=1}^{k}F[i][j] = \sum_{i=1}^n\sum_{j=1}^{k}C(j+p, j+1)^i = \sum_{j=1}^{k}\sum_{i=1}^nC(j+p, j+1)^i\)。
枚举 j 然后等比数列求和即可。
注意 C(j+p, j+1) 与 C(j+p+1, j+1+1) 之间实际上是有倍数的关系(你可以把它们拆成阶乘形式以观察到这一点)。于是我们可以直接递推而不用预处理阶乘。
@accepted code@
#include<cstdio>
const int MAXM = 1299709;
const int MOD = int(1E9) + 7;
int pow_mod(int b, int p) {
int ret = 1;
while( p ) {
if( p & 1 ) ret = 1LL*ret*b%MOD;
b = 1LL*b*b%MOD;
p >>= 1;
}
return ret;
}
int prm[MAXM + 5], pcnt;
bool nprm[MAXM + 5];
void init() {
for(int i=2;i<=MAXM;i++) {
if( !nprm[i] )
prm[++pcnt] = i;
for(int j=1;1LL*i*prm[j]<=MAXM;j++) {
nprm[i*prm[j]] = true;
if( i % prm[j] == 0 )
break;
}
}
}
int solve(int p, int n, int k) {
int ans = 0, tmp = p;
for(int j=1;j<=k;j++) {
tmp = 1LL*tmp*(j + p)%MOD*pow_mod(j + 1, MOD - 2)%MOD;
if( tmp == 1 )
ans = (ans + n)%MOD;
else ans = (ans + 1LL*(pow_mod(tmp, n + 1) - 1)*pow_mod(tmp - 1, MOD-2)%MOD - 1)%MOD;
}
return (ans + MOD)%MOD;
}
int main() {
init();
int T; scanf("%d", &T);
for(int i=1;i<=T;i++) {
int c, n, k; scanf("%d%d%d", &c, &n, &k);
printf("%d\n", solve(prm[c], n, k));
}
}
@details@
似乎总喜欢废话很多。。。明明一个不是很复杂的题目却写了这么多东西。。。
这道题有一个点就是:等比数列要特判公比为 1 的情况。
。。。虽然数学上经常考这个东西,不过还是没记住。。。
@hdu - 6372@ sacul的更多相关文章
- HDOJ 2111. Saving HDU 贪心 结构体排序
Saving HDU Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 【HDU 3037】Saving Beans Lucas定理模板
http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...
- hdu 4859 海岸线 Bestcoder Round 1
http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...
- HDU 4569 Special equations(取模)
Special equations Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u S ...
- HDU 4006The kth great number(K大数 +小顶堆)
The kth great number Time Limit:1000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64 ...
- HDU 1796How many integers can you find(容斥原理)
How many integers can you find Time Limit:5000MS Memory Limit:32768KB 64bit IO Format:%I64d ...
- hdu 4481 Time travel(高斯求期望)(转)
(转)http://blog.csdn.net/u013081425/article/details/39240021 http://acm.hdu.edu.cn/showproblem.php?pi ...
- HDU 3791二叉搜索树解题(解题报告)
1.题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=3791 2.参考解题 http://blog.csdn.net/u013447865/articl ...
- hdu 4329
problem:http://acm.hdu.edu.cn/showproblem.php?pid=4329 题意:模拟 a. p(r)= R'/i rel(r)=(1||0) R ...
随机推荐
- Pull Request的过程、基于git做的协同开发、git常见的一些命令、git实现代码的review、git实现版本的管理、gitlab、GitHub上为开源项目贡献代码
前言: Pull Request的流程 1.fork 首先是找到自己想要pull request的项目, 然后点击fork按钮,此时就会在你的仓库中多出来一个仓库,格式是:自己的账户名/想要pull ...
- python 全局种子与局部种子
- NoSQL最新现状和趋势:云NoSQL数据库将成重要增长引擎
NoSQL最早起源于1998年,但从2009年开始,NoSQL真正开始逐渐兴起和发展.回望历史应该说NoSQL数据库的兴起,完全是十年来伴随互联网技术,大数据数据的兴起和发展,NoSQL在面临大数据场 ...
- oracle -视图 序列 约束
1.视图 视图是基于一个或者多个表数据库对象,视图允许用户创建一个无数据的”伪表“,视图只是一个获取特定列好行的sql查询组成,通过视图检索数据就像从表中检索数据 一样. 视图可以提供一个附加的安全层 ...
- 词袋和 TF-IDF 模型
做文本分类等问题的时,需要从大量语料中提取特征,并将这些文本特征变换为数值特征.常用的有词袋模型和TF-IDF 模型 1.词袋模型 词袋模型是最原始的一类特征集,忽略掉了文本的语法和语序,用一组无序的 ...
- GDOI模拟4.11~4.13总结
总体情况 省选前的第一场模拟,就连续三天垫底滚粗了. 三天下来,只做了第一天的签到题,然后再做了一些水题的暴力,还不得分. 三天分数:100/400+40/400+90/400=230/1200,得了 ...
- 编码之Base64编码
Base64编码 是一种基于 64 个可打印字符来表示二进制数据的方法.目前 Base64 已经成为网络上常见的传输 8 位二进制字节代码的编码方式之一. 为什么会有 Base64 编码呢?因为有些网 ...
- TypeScript高级类型
交叉类型 将多个类型合并成一个类型,去两个类型的并集.与继承的区别是,继承可以有自己的属性,而交叉没有. interface DogInterface { run():void } interface ...
- pl/sql 语句块循环语句
---基本循环declarev1 number(2) :=1;begin loop dbms_output.put_line(v1); v1:=v1+1; exit when v1>10; -- ...
- phpcms万能字段的使用方法
今天想做一个单选的字段,里面要使用别的字段,于是研究了一下万能字段!刚开始使用的时候,在网上,论坛里找了好久,没发现一个贴子有针对万能字段的使用说明,官方的例子里也只有一个调用字段本身值的变量 {FI ...