题目描述

随着iPig在P++语言上的造诣日益提升,他形成了自己一套完整的代码库。猪王国想参加POI的童鞋们都争先恐后问iPig索要代码库。iPig不想把代码库给所有想要的小猪,只想给其中的一部分既关系好又肯出钱的小猪,于是他决定举行了一个超大型拍卖会。

在拍卖会上,所有的N头小猪将会按照和iPig的好感度从低到高,从左到右地在iPig面前站成一排。每个小猪身上都有9猪币(与人民币汇率不明),从最左边开始,每个小猪依次举起一块牌子,上面写上想付出的买代码库的猪币数量(1到9之间的一个整数)。大家都知道,如果自己付的钱比左边的猪少,肯定得不到梦寐以求的代码库,因此从第二只起,每只猪出的钱都大于等于左边猪出的价钱。最终出的钱最多的小猪(们)会得到iPig的代码库真传,向着保送PKU(Pig Kingdom University)的梦想前进。

iPig对自己想到的这个点子感到十分满意,在去现场的路上,iPig就在想象拍卖会上会出现的场景,例如一共会出现多少种出价情况之类的问题,但这些问题都太简单了,iPig早已不敢兴趣了,他想要去研究更加困难的问题。iPig发现如果他从台上往下看,所有小猪举的牌子从左到右将会正好构成一个N位的整数,他现在想要挑战的问题是所有可能构成的整数中能正好被P整除的有多少个。由于答案过大,他只想要知道答案mod 999911659就行了。

输入输出格式

输入格式:

输入文件auction.in有且仅有一行:两个数N(1≤N≤10^18)、P(1≤P≤500),用一个空格分开。

输出格式:

输入文件auction.out有且仅有一行:一个数,表示答案除以999911659的余数。

输入输出样例

输入样例#1: 复制

2 3
输出样例#1: 复制

15

说明

样例解释

方案可以是:12 15 18 24 27 33 36 39 45 48 57 66 69 78 99,共15种。

数据规模

题解

  这题太神仙了……题解看都看不懂……最后基本只能硬生生的理解了……

  首先,我们考虑数列,原数列是一个不降的序列

  考虑如下数列,$1,1,2,3,4$

  这样我们是相当于竖着分割的

  那么怎么转换为横着分割呢?我们可以记录大于等于$1$的数的个数,为$5$,大于等于$2$的数的个数,为$3$……

  那么最后原数列可以转化为$11111,111,11,1$(每个数用相同个数的$1$表示),然后我们惊奇的发现他们的和和原来的$n$位数是一样的,也就是说,他们构成的整数取模之后也是一样的!

  这就相当于在每一个位置放相当于权值大小的石头,我们一开始是竖着分,而第二种方法是横着分割

  如果竖着分割,总共有$n$个数,如果横着割,把所有模$p$同余的看成一类,那么总共只有$p$个数(因为0,1,11,111这样下去模$p$的值肯定能构成一个循环节,所以只需要计算$p$次,剩下的可以直接计算)

  那么我们为什么不转化为横着分割呢?设$cnt[i]$表示模$p$为$i$的数的个数,那么题目就变成从$cnt[i]$中取$9$个使下标之和被$p$整除

  那么就可以转化为dp了,设$f[i][j][k]$表示考虑到第$i$个数,选了$k$个,他们的和模$p$为$j$,那么状态转移方程就是$f[i+1][(j+l*i)%mod][k+l]=(f[i][j][k]*C_{cnt_i}^l+f[i+1][(j+l*i)%mod][k+l])%mod$

  然后要先考虑加上一个$11111$($n$个$1$),因为我们dp的时候是允许有前导$0$的,所以得先强制至少为$1$才行

  细节有点多,都写在注解里了

 //minamoto
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int mod=;
ll ans,n,p,cnt[],beg,len,pos[],A[],c[][],f[][][],a;
int main(){
scanf("%lld%d",&n,&p);
ll sum=;
if(n<=p){
//直接把循环节跑出来
for(int i=;i<=n;++i) sum=(sum*+)%p,++cnt[sum];
a=sum;
}else{
//否则去找循环节,数出每一个余数的出现次数
for(int i=;i<=p+;++i){
sum=(sum*+)%p;
if(cnt[sum]){
beg=pos[sum],len=i-pos[sum];
break;
}
++cnt[sum],pos[sum]=i;
}
for(int i=;i<p;++i)
if(cnt[i]&&pos[i]>=beg){
cnt[i]=(n-beg+)/len;
if(pos[i]-beg+<=(n-beg+)%len) ++cnt[i];
if((pos[i]-beg+)%len==(n-beg+)%len) a=i;
}
}
A[]=,A[]=;
for(int i=;i<=;++i)
A[i]=(mod-mod/i)*A[mod%i]%mod;
for(int i=;i<p;++i){
c[i][]=;
if(cnt[i])
for(int j=;j<=;++j){
c[i][j]=cnt[i]*c[i][j-]%mod*A[j]%mod;
cnt[i]=(cnt[i]+)%mod;
//C(n,m-1)->C(n,m)
//C(n,m-1)/m*(n-m+1)=C(n,m)
//cnt[i]=n-m+1
}
}
f[][a][]=;
//默认加n个1,因为dp的时候可以有前缀0
for(int i=;i<p;++i)
for(int j=;j<p;++j)
for(int k=;k<;++k)
for(int l=;l<=k;++l)
(f[i+][j][k]+=f[i][(j-(l*i%p)+p)%p][k-l]*c[i][l]%mod)%mod;
for(int i=;i<=;++i) (ans+=f[p][][i])%=mod;
printf("%lld\n",ans);
return ;
}

BZOJ 1974 [Sdoi2010] auction 代码拍卖会(数位dp)的更多相关文章

  1. BZOJ 1974: [Sdoi2010]auction 代码拍卖会( dp )

    在1, 11, 111……中选<=8个, + 11..(n个1)拼出所有可能...这些数mod p至多有p中可能, 找出循环的处理一下. 那么dp就很显然了...dp(i, j, k)表示前i种 ...

  2. BZOJ 1974 [Sdoi2010]auction 代码拍卖会 ——动态规划

    把每一位上不递减的数拆成1+11+11111+11111+..... 然后就可以把巨大的N从复杂度中消掉,因为随着长度的增加1...111%p出现了循环节. 然后就是从n个数中选出几个使他们结果为0( ...

  3. Bzoj1974 [Sdoi2010]auction 代码拍卖会

    Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 375  Solved: 151 Description 随着iPig在P++语言上的造诣日益提升,他形成 ...

  4. 【BZOJ-1974】auction代码拍卖会 DP + 排列组合

    1974: [Sdoi2010]auction 代码拍卖会 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 305  Solved: 122[Submit ...

  5. bzoj 1026 [SCOI2009]windy数(数位DP)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4550  Solved: 2039[Submit][Sta ...

  6. bzoj 1026: [SCOI2009]windy数【数位dp】

    忘记limit不能记WA了一发-- 典型数位dp,变成work(r)-work(l-1),然后dfs的时候记录w当前位置,la上一个数选的什么,lm当前位是否有上限,ok当前位是否可以不考虑差大于等于 ...

  7. bzoj 3209 花神的数论题 —— 数位DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3209 算是挺简单的数位DP吧,但还是花了好久才弄明白... 又参考了博客:https://b ...

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

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

  9. BZOJ 3209 花神的数论题 数位DP+数论

    题目大意:令Sum(i)为i在二进制下1的个数 求∏(1<=i<=n)Sum(i) 一道非常easy的数位DP 首先我们打表打出组合数 然后利用数位DP统计出二进制下1的个数为x的数的数量 ...

随机推荐

  1. 【转】rails 遇到 Could not find a JavaScript runtime execjs错误(ubuntu)

    当我运行 $rails s 遇到下面错误 sudo apt-get install python-software-properties sudo add-apt-repository ppa:chr ...

  2. java--构造器与static

    原本无显示编码构造器,则有一个默认的隐式(隐藏的无参构造器),但是,当显示指定了构造器,则这个默认隐式的构造器将不存在,比如此时无法new无参的构造器(除非显示地编写声明无参的构造函数). 如果子类构 ...

  3. paramiko远程执行命令成功

  4. Nginx简单入门教学,包学包会,让你不再依赖伪大神!

    这篇教程简单介绍了 nginx 并且讲解了一些 nginx 可以解决的简单任务.这里,我们假设 nginx 已经安装在读者的机器上.如果没有,可以看一下如何安装 nginx.这篇教程主要讲解的是如果启 ...

  5. 类型:.net;问题:C#lambda表达式;结果:Lambda表达式详解

    Lambda表达式详解   前言 1.天真热,程序员活着不易,星期天,也要顶着火辣辣的太阳,总结这些东西. 2.夸夸lambda吧:简化了匿名委托的使用,让你让代码更加简洁,优雅.据说它是微软自c#1 ...

  6. fluent仿真数值错误

  7. 用SSIS包导入数据

    创建一个简单ETL包.打开 Step 1:创建新的Integration Services项目 在开始菜单中找到SQL Server Data Tools并打开,在Microsoft SQL Serv ...

  8. ActiveMQ (一) 介绍与安装

    ActiveMQ是消息中间件的一种 ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provide ...

  9. day17 12.复习

    最后能抽取成word文档或者是图片之类的. 1.jdbc介绍  jdbc是一套标准,可以让我们Java程序员通过Java代码直接操作数据库,这就够了.jdbc涉及到的包两个:java.sql,java ...

  10. 友善之臂smart210 3G网卡配置说明

    1.命令行输入 3g-ppp /etc/3g-modem/12d1.1446.12d1.1001 2.call-ppp wcdma 3.  你到etc目录里grep一下192.168.1.1 sant ...