[CSP-S模拟测试]:密码(数位DP+库默尔定理)
题目描述
为了揭穿$SERN$的阴谋,$Itaru$黑进了$SERN$的网络系统。
然而,想要完全控制$SERN$,还需要知道管理员密码。$Itaru$从截获的信息中发现,$SERN$的管理员密码是两个整数$l,s,0\leqslant s\leqslant l$,并且一旦得知了管理员密码,就可以生成出$SERN$各个网路接口的密码:各个网络接口的密码均是若干个长为$l$的$0/1$串,且每个串中$1$的个数恰为$s$。不难发现,生成的密码串个数是一个组合数。
$SERN$的网络系统是由$p^k$个网络接口构成的,$SERN$为了保证网络系统的稳定性,保证了$p$为质数,且所有生成的密码串个数能被$p^k$整除。为了网络通讯的方便,$SERN$的网络接口的密码不会太长,即可以保证$l\leqslant N$。
作为一名$Super\ Hacker$,$Itaru$已经想到了破解密码的绝妙方法,然而在这之前,他需要确认管理员密码的可能情况有多少。由于答案可能很大,答案对${10}^9+7$取模。
输入格式
仅包含一行三个整数$N,p,k$。
输出格式
仅包含一个整数,表示答案。
样例
样例输入:
4 2 2
样例输出:
2
数据范围与提示
样例解释:
有$2$种可能的情况,$l=4,s=1;l=4s=3$。
数据范围:
保证$1\leqslant p,k\leqslant {10}^9,1\leqslant N\leqslant {10}^{1000}$,$p$为质数。
各个测试点还满足如下约束:
题解
又是数学题,那就化式子。
组合数与阶乘有关,我们可以先考虑阶乘。
对于$n!$,满足$p^k|n!$的最大的$k$为:$$maxk=\sum \limits_{i=1}^{\infty}\left \lfloor \frac{n}{p^i}\right \rfloor$$
那么对于$C_n^m$,由于$C_n^m=\frac{n!}{m!(n-m)!}$,满足$p^k|C_n^m$的最大的$k$为:$$maxk=\sum \limits_{i=1}^{\infty}\left \lfloor \frac{n}{p^i}\right \rfloor-\left \lfloor \frac{m}{p^i}\right \rfloor-\left \lfloor \frac{n-m}{p^i}\right \rfloor \left \lfloor \frac{n-m}{p^i}\right \rfloor$$
然后我们引入一个新的名词:库默尔定理。
那么,什么是库默尔定理呢?
设$m,n$为正整数,$p$为素数,则$C_{m+n}^m$含$p$的幂次等于$m+n$在$p$进制下的进位次数。
下面给出证明:
组合数$C_{n+m}^m$所含$p$的幂次数为:$$\sum \limits_{i=1}^{\infty}\left \lfloor \frac{m+n}{p^i}\right \rfloor-\sum \limits_{i=1}^{\infty}\left \lfloor \frac{n}{p^i}\right \rfloor-\sum \limits_{i=1}^{\infty}\left \lfloor \frac{m}{p^i}\right \rfloor \\ =\sum \limits_{i=1}^{\infty}(\left \lfloor \frac{m+n}{p^i}\right \rfloor-\left \lfloor \frac{n}{p^i}\right \rfloor-\left \lfloor \frac{m}{p^i}\right \rfloor)$$
这是因为组合数公式$C_{n+m}^n=\frac{(n+m)!}{n!m!}$以及$n!$含有素数$p$的幂次公式$vp(n!)=\sum \limits_{i=1}^{\infty} \left \lfloor \dfrac{n}{p^i}\right \rfloor$。
对于某个$p^i$,$\left \lfloor \frac{m}{p^i}\right \rfloor$等于$m$在$p$进制表示下去掉后$i$位,在第$i+1$位上,$n+m$在这一位上进位的充要条件是$$\left \lfloor \frac{n+m}{p^i}\right \rfloor-\left \lfloor \frac{n}{p^i}\right \rfloor-\left \lfloor \frac{m}{p^i}\right \rfloor=1$$不进位则$$\left \lfloor \frac{n+m}{p^i}\right \rfloor-\left \lfloor \frac{n}{p^i}\right \rfloor-\left \lfloor \frac{m}{p^i}\right \rfloor=0$$因此$\sum \limits_{i=1}^{\infty}(\left \lfloor \frac{m+n}{p^i}\right \rfloor-\left \lfloor \frac{n}{p^i}\right \rfloor-\left \lfloor \frac{m}{p^i}\right \rfloor)$就是$n+m$在$p$进制下的进位次数。
那么题目所求便是两个和不超过$N$的正整数,它们在$p$进制下做加法近位了至少$k$的可能方案数。
那么考虑数位$DP$,设$dp[i][j][0/1][0/1]$表示到了$p$进制下的第$i$位,进位次数为$j$,下一位是否进位,前$i$位是否与$N$在$p$进制下相同的方案。
时间复杂度:$\Theta(S^2)$设$S$为$N$在$p$进制下的位数。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h>
using namespace std;
char ch[1001];
long long N[1001],S[1001];
long long p,k;
long long dp[1001][1001][2][2];
long long ans;
int main()
{
scanf("%s%lld%lld",ch+1,&p,&k);
N[0]=strlen(ch+1);
for(int i=1;i<=N[0];i++)N[i]=ch[i]-'0';
for(int i=1;(i<<1)<=N[0];i++)
N[i]^=N[N[0]-i+1]^=N[i]^=N[N[0]-i+1];
while(N[0])
{
for(int i=N[0];i;i--)
{
if(i>1)N[i-1]+=N[i]%p*10;
else S[++S[0]]=N[i]%p;
N[i]/=p;
}
while(N[0]&&!N[N[0]]){N[0]--;if(N[0]<0){puts("0");return 0;}}
}
dp[0][0][0][0]=1;
for(int i=1;i<=S[0];i++)
for(int j=0;j<=i;j++)
{
dp[i][j][0][0]=(((S[i]+1)*(S[i]+2)>>1)%1000000007*dp[i-1][j][0][0]%1000000007+(S[i]*(S[i]+1)>>1)%1000000007*(dp[i-1][j][0][1]+dp[i-1][j][1][0])%1000000007+(S[i]*(S[i]-1)>>1)%1000000007*dp[i-1][j][1][1]%1000000007)%1000000007;
dp[i][j+1][0][1]=((((p<<1)-S[i]-2)*(S[i]+1)>>1)%1000000007*dp[i-1][j][0][0]%1000000007+(((p<<1)-S[i])*(S[i]+1)>>1)%1000000007*dp[i-1][j][0][1]%1000000007+(((p<<1)-S[i]-1)*S[i]>>1)%1000000007*dp[i-1][j][1][0]%1000000007+(((p<<1)-S[i]+1)*S[i]>>1)%1000000007*dp[i-1][j][1][1]%1000000007)%1000000007;
dp[i][j][1][0]=(((S[i]+p+2)*(p-S[i]-1)>>1)%1000000007*dp[i-1][j][0][0]%1000000007+((p+S[i])*(p-S[i]-1)>>1)%1000000007*dp[i-1][j][0][1]%1000000007+((p+S[i]+1)*(p-S[i])>>1)%1000000007*dp[i-1][j][1][0]%1000000007+((p+S[i]-1)*(p-S[i])>>1)%1000000007*dp[i-1][j][1][1]%1000000007)%1000000007;
dp[i][j+1][1][1]=(((p-S[i]-2)*(p-S[i]-1)>>1)%1000000007*dp[i-1][j][0][0]%1000000007+((p-S[i])*(p-S[i]-1)>>1)%1000000007*(dp[i-1][j][0][1]+dp[i-1][j][1][0])%1000000007+((p-S[i]+1)*(p-S[i])>>1)%1000000007*dp[i-1][j][1][1]%1000000007)%1000000007;
}
for(int i=k;i<=S[0];i++)
ans=(ans+dp[S[0]][i][0][0])%1000000007;
printf("%lld",ans);
return 0;
}
rp++
[CSP-S模拟测试]:密码(数位DP+库默尔定理)的更多相关文章
- CF582D Number of Binominal Coefficients 库默尔定理 数位dp
LINK:Number of Binominal Coefficients 原来难题都长这样.. 水平有限只能推到一半. 设\(f(x)\)表示x中所含p的最大次数.即x质因数分解之后 p的指标. 容 ...
- [CSP-S模拟测试]:密码(AC自动机+DP)
题目传送门(内部题19) 输入格式 第一行两个正整数$n,k$,代表秘钥个数和要求.接下来两个正整数$x$和$y$,意义如题所述.接下来$n$行,每行一个正整数,意义如题所述. 输出格式 一个正整数, ...
- 2018.06.26 NOIP模拟 号码(数位dp)
题目背景 SOURCE:NOIP2015-GDZSJNZX(难) 题目描述 Mike 正在在忙碌地发着各种各样的的短信.旁边的同学 Tom 注意到,Mike 发出短信的接收方手机号码似乎都满足着特别的 ...
- 2018.08.18 NOIP模拟 game(数位dp)
Game 题目背景 SOURCE:NOIP2015-SHY4 题目描述 Alice 和 Bob 正在玩一个游戏,两个人从 1 轮流开始报数,如果遇到 7 的倍数或者遇到的这个数的十进制表示中含 7 , ...
- [bzoj3209][花神的数论题] (数位dp+费马小定理)
Description 背景众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦.描述话说花神这天又来讲课了.课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了. ...
- scauoj 18025 小明的密码 数位DP
18025 小明的密码 时间限制:4000MS 内存限制:65535K提交次数:0 通过次数:0 题型: 编程题 语言: G++;GCC Description 小明的密码由N(1<=N& ...
- [CSP-S模拟测试]:B(DP+数学)
题目传送门(内部题45) 输入格式 第一行$3$个整数$n,m,P$.第二行$m$个整数,表示$m$次询问. 输出格式 一行$m$个整数表示答案. 样例 样例输入1: 2 4 40 1 2 3 样例输 ...
- [CSP-S模拟测试]:蛇(DP+构造+哈希)
题目传送门(内部题140) 输入格式 前两行有两个长度相同的字符串,描述林先森花园上的字母. 第三行一个字符串$S$. 输出格式 输出一行一个整数,表示有多少种可能的蛇,对$10^9+7$取模. 样例 ...
- [CSP-S模拟测试]:最小值(DP+乱搞)
题目背景 $Maxtir$更喜欢序列的最小值. 题目传送门(内部题128) 输入格式 第一行输入一个正整数$n$和四个整数$A,B,C,D$. 第二行输入$n$个整数,第$i$个数表示$a_i$. 输 ...
随机推荐
- Linq操作之Except,Distinct,Left Join 【转】
最近项目中用到了Linq中Except,Distinct,Left Join这几个运算,这篇简单的记录一下这几种情形. Except 基础类型使用Linq的运算很简单,下面用来计算两个集合的 ...
- react绑定事件的几种写法
方法一:最麻烦的写法,不推荐 import React from 'react'; class App extends React.Component { handleClick() { alert( ...
- node jade || ejs引擎模板
1.jade:破坏式2.ejs:保留式 -------------------------------------------------------------------------------- ...
- 短信对接——一种jdbc链接运用
package sms; import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamRead ...
- JVM学习(三):垃圾回收算法
局部性原理和分代回收思想 大学学习操作系统或者计算机组成原理的时候都提到一个重要概念,叫局部性原理. 局部性原理是指CPU访问存储器时,无论是存取指令还是存取数据,所访问的存储单元都趋于聚集在一个较小 ...
- 中断或取消Promise链的可行方案
ES6标准引入的异步编程解决方案Promise,能够将层层嵌套的回调转化成扁平的Promise链式调用,优雅地解决了“回调地狱”的问题.当Promise链中抛出一个错误时,错误信息沿着链路向后传递,直 ...
- Delphi 使用数据库浏览器
樊伟胜
- Oracle【多表查询操作(SQL92&SQL99)】
多表联合查询:需要获取的数据分布在多张表中 SQL92: --笛卡尔积:将多个表的数据进行一一对应,所得的结果为多表的笛卡尔积 select * from emp; select * from dep ...
- apache简介与安装
1.1 apache简介 apache当前全世界排名点击这里 1.1.1 当前互联网主流web服务说明 静态服务 apache --->中小型静态web服务的主流,web服务器中的老大哥 ngi ...
- bom操作,事件与jquery
BOM操作中 window关键字 可以不写 DOM操作 学习如何查找节点 如何查找标签 选择器 事件 当符合某个条件下 自动触发的动作/响应 js绑定事件的方式 方式1 不推荐使用 <butto ...