UOJ275 [清华集训2016] 组合数问题 【Lucas定理】【数位DP】
题目分析:
我记得很久以前有人跟我说NOIP2016的题目出了加强版在清华集训中,但这似乎是一道无关的题目?
由于$k$为素数,那么$lucas$定理就可以搬上台面了。
注意到$\binom{i}{j} \equiv 0 {\mod k}$当且仅当将$i$和$j$用$k$进制表示的时候,有一位上的$i<j$。
位数上的计算用数位DP就没错了。
代码:
#include<bits/stdc++.h>
using namespace std; const int mod = ; int t,k;
long long n,m; int bn[],n1,n2,bm[],nw[]; int f[][][]; //0 0~k-1 1 0~self
int sum[][],pw[],dd[],oo[],fw[],yw[]; void init(){
if(n < m) m = n;
memset(bn,,sizeof(bn)); memset(bm,,sizeof(bm)); n1 = ,n2 = ;
long long p1 = n,p2 = m;
while(p1){bn[++n1] = p1 % k; p1 /= k;}
while(p2){bm[++n2] = p2 % k; p2 /= k;}
dd[] = ;oo[] = ;
for(int i=;i<=n1;i++) dd[i] = (dd[i-] + 1ll*bm[i]*pw[i-]%mod)%mod;
for(int i=;i<=n1;i++) oo[i] = (oo[i-] + 1ll*bn[i]*pw[i-]%mod)%mod;
} pair<int,int> dfs3(int now){
if(now == ){return make_pair(,);}
int ans1 = ,ans2 = ;
pair<int,int> pt = dfs3(now-);
int cutp = min(bn[now]+,bm[now]);
for(int i=;i<bn[now];i++){
int cuep = min(i+,bm[now]);
ans1 += (1ll*cuep*sum[now-][])%mod; ans1 %= mod;
ans1 += (1ll*(bm[now]-cuep)*pw[now-])%mod*pw[now-]%mod;ans1%=mod;
if(bm[now] > i){ans1 += (1ll*pw[now-]*dd[now-])%mod; ans1 %= mod;}
else{ans1 += nw[now-];ans1 %= mod;}
ans2 += (1ll*(i+)*sum[now-][])%mod; ans2 %= mod;
ans2 += (1ll*(k-i-)*pw[now-]%mod*pw[now-])%mod; ans2 %= mod;
}
ans1 += (1ll*cutp*pt.second)%mod; ans1 %= mod;
ans1 += (1ll*(bm[now]-cutp)*oo[now-]%mod*pw[now-])%mod;ans1 %= mod;
if(bm[now] > bn[now]){ans1 += (1ll*oo[now-]*dd[now-])%mod;ans1%=mod;}
else{ans1 += pt.first;ans1 %= mod;}
ans2 += (1ll*(bn[now]+)*pt.second)%mod; ans2 %= mod;
ans2 += (1ll*(k-bn[now]-)*oo[now-])%mod*pw[now-]%mod;ans2 %= mod;
return make_pair(ans1,ans2);
} void work(){
memset(f,,sizeof(f));memset(sum,,sizeof(sum));memset(nw,,sizeof(nw));
for(int i=;i<=n1;i++){
for(int j=;j<k;j++){
f[i][j][] = (1ll*j*sum[i-][]+sum[i-][]+f[i][j][])%mod;
f[i][j][] += (1ll*(j+)*sum[i-][])%mod; f[i][j][] %= mod;
f[i][j][] += (1ll*(k-j-)*((1ll*pw[i-]*pw[i-])%mod))%mod;
f[i][j][] %= mod;
sum[i][] += f[i][j][]; sum[i][] %= mod;
sum[i][] += f[i][j][]; sum[i][] %= mod;
}
}
int ans = ;
for(int now=;now<=n1;now++){
int ans1 = ,ans2 = ;
for(int i=;i<bm[now];i++){
ans1 = (ans1 + 1ll*sum[now-][]*(i+))%mod;
ans1 +=(1ll*pw[now-]*pw[now-])%mod*(bm[now]--i)%mod;ans1%=mod;
ans1 += (1ll*pw[now-]*dd[now-])%mod; ans1 %= mod;
ans2 += (1ll*(i+)*sum[now-][])%mod; ans2 %= mod;
ans2 += ((1ll*(k-i-)*pw[now-])%mod*pw[now-])%mod; ans2 %= mod;
}
ans2 = (ans2+1ll*yw[now-]*(bm[now]+))%mod;
ans2+=((1ll*pw[now-]*(k-bm[now]-))%mod*dd[now-])%mod;ans2%=mod;
ans1 = (1ll*yw[now-]*bm[now]+fw[now-]+ans1)%mod;
fw[now] = ans1; yw[now] = ans2;
}
for(int now=;now<=n1;now++){
for(int i=;i<bm[now];i++){
nw[now] += (1ll*pw[now-]*i%mod*pw[now-])%mod; nw[now] %= mod;
nw[now] = (nw[now]+1ll*(k-i)*sum[now-][])%mod;
}
nw[now] += 1ll*bm[now]*pw[now-]%mod*dd[now-]%mod; nw[now] %= mod;
nw[now] = (nw[now]+1ll*(k-bm[now])*nw[now-])%mod;
}
ans += fw[n1];ans-=(m%mod*((m+)%mod)/2ll)%mod; if(ans < ) ans += mod;
pair<int,int> ans2 = dfs3(n1);
ans = ans + (ans2.first-fw[n1]); ans %= mod; ans += mod; ans %= mod;
printf("%d\n",ans);
} int main(){
scanf("%d%d",&t,&k);
pw[] = ; for(int i=;i<=;i++) pw[i] = (1ll*pw[i-]*k)%mod;
while(t--){
scanf("%lld%lld",&n,&m);
init(); work();
}
return ;
}
UOJ275 [清华集训2016] 组合数问题 【Lucas定理】【数位DP】的更多相关文章
- uoj86 mx的组合数 (lucas定理+数位dp+原根与指标+NTT)
uoj86 mx的组合数 (lucas定理+数位dp+原根与指标+NTT) uoj 题目描述自己看去吧( 题解时间 首先看到 $ p $ 这么小还是质数,第一时间想到 $ lucas $ 定理. 注意 ...
- [BZOJ4591][SHOI2015]超能粒子炮·改(Lucas定理+数位DP)
大组合数取模可以想到Lucas,考虑Lucas的意义,实际上是把数看成P进制计算. 于是问题变成求1~k的所有2333进制数上每一位数的组合数之积. 数位DP,f[i][0/1]表示从高到低第i位,这 ...
- BZOJ4737 组合数问题 【Lucas定理 + 数位dp】
题目 组合数C(n,m)表示的是从n个物品中选出m个物品的方案数.举个例子,从(1,2,3)三个物品中选择两个物品可以有( 1,2),(1,3),(2,3)这三种选择方法.根据组合数的定义,我们可以给 ...
- bzoj 1902: Zju2116 Christopher lucas定理 && 数位DP
1902: Zju2116 Christopher Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 172 Solved: 67[Submit][Stat ...
- uoj#268. 【清华集训2016】数据交互(动态dp+堆)
传送门 动态dp我好像还真没咋做过--通过一个上午的努力光荣的获得了所有AC的人里面的倒数rk3 首先有一个我一点也不觉得显然的定理,如果两条路径相交,那么一定有一条路径的\(LCA\)在另一条路径上 ...
- UOJ 275. 【清华集训2016】组合数问题
UOJ 275. [清华集训2016]组合数问题 组合数 $C_n^m $表示的是从 \(n\) 个物品中选出 \(m\) 个物品的方案数.举个例子,从$ (1,2,3)(1,2,3)$ 三个物品中选 ...
- UOJ #269. 【清华集训2016】如何优雅地求和
UOJ #269. [清华集训2016]如何优雅地求和 题目链接 给定一个\(m\)次多项式\(f(x)\)的\(m+1\)个点值:\(f(0)\)到\(f(m)\). 然后求: \[ Q(f,n,x ...
- UOJ #274. 【清华集训2016】温暖会指引我们前行 [lct]
#274. [清华集训2016]温暖会指引我们前行 题意比较巧妙 裸lct维护最大生成树 #include <iostream> #include <cstdio> #incl ...
- UOJ_274_[清华集训2016]温暖会指引我们前行_LCT
UOJ_274_[清华集训2016]温暖会指引我们前行_LCT 任务描述:http://uoj.ac/problem/274 本题中的字典序不同在于空串的字典序最大. 并且题中要求排序后字典序最大. ...
随机推荐
- COMCMS 微进阶篇,从0开始部署到Centos 7.4
言:上一篇,我们介绍了,如何本地调试和部署到windows服务器. 本篇,将带大家,从0到1,开始部署到Centos系统上... 经过测试,可以完美支持Centos.这也是.net core 跨平台的 ...
- DOM操作 JS事件 节点增删改查
--------------------------习惯是社会的巨大的飞轮和最可贵的维护者.——威·詹姆斯 day 49 [value属性操作] <!DOCTYPE html><ht ...
- configure: error: cannot guess build type; you must specify one解决方法
原文地址:https://blog.csdn.net/hebbely/article/details/53993141 1.configure: error: cannot guess build t ...
- Python-认识正则表达式-53
# 计算器# re模块# 正则表达式 —— 字符串匹配的# 学习正则表达式# 学习使用re模块来操作正则表达式 #判断手机号是否符合要求 while True: phone_number = inpu ...
- MySQL的常用命令:添加外键,修改字段名称,增加字段 设置主键自增长等
Mysql命令添加外键 前提是有这么几个表 以mall_product 和 mall_category为例 ALTER TABLE mall_product ADD CONSTRAINT fore_ ...
- JS 深拷贝和浅拷贝概念,以及实现深拷贝的三种方式
一.理解堆栈,基本数据类型与引用数据类型 1.堆栈 栈(stack):系统自动分配的内存空间,内存会由系统自动释放,用来存放函数的参数值,局部变量的值等,特点是先进后出. 堆(heap):系统动态分配 ...
- PS 制作彩色烟雾
- 【学习总结】Git学习-参考廖雪峰老师教程八-使用GitHub
学习总结之Git学习-总 目录: 一.Git简介 二.安装Git 三.创建版本库 四.时光机穿梭 五.远程仓库 六.分支管理 七.标签管理 八.使用GitHub 九.使用码云 十.自定义Git 期末总 ...
- 【Python3练习题 012】 输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。
ASCII 码表的对应值,知道 ord('a') 能将字符 'a' 转化为 ASCII 码表上对应的数值,就可以了.其中,数字 0-9 对应的码值为 48-57,大写字母 A-Z 对应 65-90,小 ...
- composer 自动加载 通过classmap自动架子啊
https://github.com/brady-wang/composer github地址 composer加载自己写的类 放入一个目录下 更改composer.json "autolo ...