题目

组合数C(n,m)表示的是从n个物品中选出m个物品的方案数。举个例子,从(1,2,3)三个物品中选择两个物品可以有(

1,2),(1,3),(2,3)这三种选择方法。根据组合数的定义,我们可以给出计算组合数C(n,m)的一般公式:
C(n,m)=n!/m!*(n?m)!
其中n!=1×2×?×n。(额外的,当n=0时,n!=1)
小葱想知道如果给定n,m和k,对于所有的0≤i≤n,0≤j≤min(i,m)有多少对(i,j)满足C(i,j)是k的倍数。

输入格式

第一行有两个整数t,k,其中t代表该测试点总共有多少组测试数据,k的意义见。
接下来t行每行两个整数n,m,其中n,m的意义见。

输出格式

t行,每行一个整数代表所有的0≤i≤n,0≤j≤min(i,m)中有多少对(i,j))满足C(i,j)是k的倍数

答案对10^9+7取模。

输入样例

3 23

23333333 23333333

233333333 233333333

2333333333 2333333333

输出样例

851883128

959557926

680723120

提示

1≤n,m≤10^18,1≤t,k≤100,且 k 是一个质数

题解

根据\(Lucas\)定理我们知道,在模质数\(k\)下
\[{n \choose m} \equiv \prod_{i = 1} {\lfloor \frac{n}{k^{i - 1}} \rfloor \mod k^i \choose \lfloor \frac{m}{k^{i - 1}} \rfloor \mod k^i} \pmod k\]
由此,结果为\(0\),当且仅当存在一个\(i\),使得\({n \mod k^i \choose m \mod k^i} \equiv 0 \pmod k\)
一个组合数在模质数意义下为0,当且仅当\(n < m\)
一个组合数在模质数意义下不为0,那么就是\(n >= m\)

那么我们将\(n\)和\(m\)拆分为\(k\)进制数,就可以设一个dp:
\(f[i][0/1][0/1]\)表示第\(i\)位之前(\(n\)是否达到上界) (\(m\)是否达到上界) 的\(n >= m\)方案数,即不为\(0\)的方案数
最后用总方案减去就可以了
转移就自己推推

要注意乘法可能溢出,要用快速乘

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
#define cls(s) memset(s,0,sizeof(s))
using namespace std;
const int maxn = 105,maxm = 100005,INF = 1000000000,P = 1e9 + 7;
LL n,m,f[maxn][2][2],a[maxn],b[maxn],ai,bi,N,K,v2;
LL qpow(LL a,LL b){LL ans = 1;for (; b; b >>= 1,a = a * a % P)if (b & 1) ans = ans * a % P;return ans;
}
void add(LL& a,LL b){a += b;if (a >= P) a -= P;
}
LL Mul(LL a,LL b){LL re = 0;for (; b; b >>= 1,a = (a + a) % P) if (b & 1) re = (re + a) % P;return re;
}
LL S(LL x){return Mul(x,x + 1) * v2 % P;}
int main(){int T; scanf("%d%lld",&T,&K); v2 = qpow(2,P - 2);while (T--){cls(a); cls(b); cls(f);scanf("%lld%lld",&n,&m); ai = bi = 0;LL ans = S(min(n,m) + 1);ans = (ans + Mul(m + 1,max(n - m,0ll))) % P;while (n) a[++ai] = n % K,n /= K;while (m) b[++bi] = m % K,m /= K;N = max(ai,bi);f[N][1][1] = 1;for (int i = N; i; i--){//0 0add(f[i - 1][0][0],S(K) * f[i][0][0] % P);//0 1add(f[i - 1][0][0] ,(S(b[i]) + b[i] * (K - b[i]) % P) % P * f[i][0][1] % P);add(f[i - 1][0][1],(K - b[i]) * f[i][0][1] % P);//1 0add(f[i - 1][0][0],S(a[i]) * f[i][1][0] % P);add(f[i - 1][1][0],(a[i] + 1) * f[i][1][0] % P);//1 1if (a[i] >= b[i]){add(f[i - 1][0][0],(S(b[i]) + b[i] * ((a[i] - b[i] + P) % P) % P) % P * f[i][1][1] % P);add(f[i - 1][1][0],b[i] * f[i][1][1] % P);add(f[i - 1][0][1],(a[i] - b[i] + P) % P * f[i][1][1] % P);add(f[i - 1][1][1],f[i][1][1]);}else {add(f[i - 1][0][0],S(a[i]) * f[i][1][1] % P);add(f[i - 1][1][0],(a[i] + 1) % P * f[i][1][1] % P);}}for (int i = 0; i < 2; i++)for (int j = 0; j < 2; j++)ans = (ans - f[0][i][j] + P) % P;printf("%lld\n",(ans % P + P) % P);}return 0;
}

转载于:https://www.cnblogs.com/Mychael/p/8971840.html

BZOJ4737 组合数问题 【Lucas定理 + 数位dp】相关推荐

  1. [BZOJ4591][SHOI2015]超能粒子炮·改(Lucas定理+数位DP)

    大组合数取模可以想到Lucas,考虑Lucas的意义,实际上是把数看成P进制计算. 于是问题变成求1~k的所有2333进制数上每一位数的组合数之积. 数位DP,f[i][0/1]表示从高到低第i位,这 ...

  2. bzoj 1902: Zju2116 Christopher lucas定理 数位DP

    1902: Zju2116 Christopher Time Limit: 1 Sec  Memory Limit: 64 MB Submit: 172  Solved: 67 [Submit][St ...

  3. BZOJ4591 SHOI2015超能粒子炮·改(卢卡斯定理+数位dp)

    注意到模数很小,容易想到使用卢卡斯定理,即变成一个2333进制数各位组合数的乘积.对于k的限制容易想到数位dp.可以预处理一发2333以内的组合数及组合数前缀和,然后设f[i][0/1]为前i位是否卡 ...

  4. loj 300 [CTSC2017]吉夫特 【Lucas定理 + 子集dp】

    题目链接 loj300 题解 orz litble 膜完题解后,突然有一个简单的想法: 考虑到\(2\)是质数,考虑Lucas定理: \[{n \choose m} = \prod_{i = 1} { ...

  5. 花神的数论题(这题...哎。数位dp咋就这么 not naive 呢)

    题意简介 没什么好说,就是让你求出 1 ~ n 之间每个数转化为二进制后 '1' 的个数,然后乘起来输出积 题目分析 emmmm.... 两种解法(同是 $O(\log^2 N)$ 的算法,组合数效率 ...

  6. BZOJ 2111 [ZJOI2010]Perm 排列计数:Tree dp + Lucas定理

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2111 题意: 给定n,p,问你有多少个1到n的排列P,对于任意整数i∈[2,n]满足P[i ...

  7. 洛谷P3773 [CTSC2017]吉夫特(Lucas定理,dp)

    题意 满足$b_1 < b_2 < \dots < b_k$且$a_{b_1} \geqslant a_{b_2} \geqslant \dots \geqslant a_{b_k} ...

  8. [Swust OJ 247]--皇帝的新衣(组合数+Lucas定理)

    题目链接:http://acm.swust.edu.cn/problem/0247/ Time limit(ms): 1000 Memory limit(kb): 65535 Description ...

  9. [CTSC2017]吉夫特(Lucas定理,DP)

    送70分,预处理组合数是否为偶数即可. 剩下的数据,根据Lucas定理的推论可得当且仅当n&m=n的时候,C(n,m)为奇数. 这样就可以直接DP了,对于每个数,考虑它对后面的数的影响即可,直 ...

最新文章

  1. Kali Linux 安全渗透教程第五更1.4 安装Kali Linux
  2. 额外域建立FSMO角色转移及夺取
  3. 搭建EJB3开发环境
  4. 阿里云张献涛:一切从场景出发,实现计算的全场景覆盖
  5. 分布式与人工智能课程(part10)--图像库的基本使用
  6. Windows UI风格的设计(11)
  7. php datetime 对象,PHP DateTime 对象和 Date 函数的 Demo
  8. Codeforces Round #301 (Div. 2) C. Ice Cave BFS
  9. 咨询笔记:麦肯锡7步成诗
  10. SQL无所不能:DBA宝妈宝爸系列分享
  11. ansible基本模块-copy
  12. convert py to pyd
  13. 搭建Android开发环境(超详细)
  14. 对接饿了么 获取授权
  15. 微信公共号开发教程java版——微信网页授权(八)
  16. Python:实现binomial distribution二项分布算法(附完整源码)
  17. MGRE环境下的OSPF (实验超详解)
  18. Ardunio开发实例-LM75温度传感器
  19. 【通信协议】单总线协议详解——以DHT11为例
  20. 云储存服务器系统内蒙古,内蒙古【存储服务器】怎么选_星际云储

热门文章

  1. SpringCloud系列十三:Feign对继承、压缩、日志的支持以及构造多参数请求
  2. ntpd时钟同步服务
  3. codefores 204E. Little Elephant and Strings(后缀数组,RMQ求lcp,二分,主席树)
  4. 浮点数规格化-不同基数的规格化
  5. [洛谷P1342]请柬
  6. xhtml html
  7. webpack 编译完成执行代码
  8. 20145236 《Java程序设计》 第6周学习总结
  9. (01)System Verilog 程序数据采集
  10. (27)FPGA面试题动态时序模拟