\(\mathcal{Description}\)

  给定 \(n,m,p\),求序列 \(\{a_n\}\) 的数量,满足 \((\forall i\in[1,n])(a_i\in[1,m])\land(\forall i\in(1,n])(a_{i-1}\le a_i)\land\left(\sum_{i=1}^na_i10^{n-i}\bmod p=0\right)\),对 \(998244353\) 取模。

  \(n\le10^{18}\),\(m\le50\),\(p\le200\)。

\(\mathcal{Solution}\)

  肯定要利用 \(10^x\) 在\(\bmod p\) 意义下存在循环节的性质来求解。考场上想到暴力扫前 \(\mathcal O(p)\) 个 DP 状态然后用倍增来求解,不过死掉了 qwq。

  转化题意——因为序列单调不减,记 \(1_n=\underbrace{11\cdots1}_{n\text{个}1}\),那么任意一种序列所对应的 \(\sum_{i=1}^na_i10^{n-i}\) 都可以由若干个 \(1_x\) 相加得到。为了保证 \(a_i\ge1\),我们钦定一个 \(1_n\) 计入贡献。而显然 \(1_x\) 在\(\bmod p\) 意义下亦存在循环节,我们可以求出 \(c_i\) 表示有 \(c_i\) 个 \(1_x\bmod p=i~(x\in[1,n])\)。问题就转化成:有 \(p\) 物品,第 \(i\) 类物品权值为 \(i\),有 \(c_i\) ,每种有无数个,求选出 \(m-1\) 物品使得其权值和\(\bmod p=0\) 的方案数。

  接下来类似背包 DP,定义 \(f(i,j,k)\) 表示决定了前 \(i\) 类物品,已选了 \(j\) 个,权值和\(\bmod p=k\) 的方案数。转移枚举第 \(i+1\) 类所选个数 \(t\),用隔板法计算方案,有:

\[f(i+1,j+t,(k+t(i+1))\bmod p)\leftarrow f(i,j,k)\binom{c_{i+1}+t-1}{c_{i+1}-1}
\]

  特别留意初始状态应为 \(f(-1,0,1_n\bmod p)=1\),因为种类编号从 \(0\) 开始;预先钦定了一个 \(1_n\)。

  复杂度 \(\mathcal O(m^2p^2)\)。

\(\mathcal{Code}\)

#include <cstdio>

typedef long long LL;
#define int LL const int MOD = 998244353, MAXM = 50, MAXP = 200;
LL n, buc[MAXP + 5];
int m, p, visc[MAXP + 5], suf[MAXP + 5], inv[MAXM + 5];
int f[2][MAXM + 5][MAXP + 5]; inline void addeq ( int& a, const int b ) { if ( ( a += b ) >= MOD ) a -= MOD; } inline void total ( const int fir, const int cnt ) {
bool onc[MAXP + 5] = {};
LL cirs = cnt - visc[fir], cirt = n - cnt + cirs + 1;
for ( int i = fir, stp = 1; stp <= cirs; i = suf[i], ++ stp ) {
onc[i] = true;
buc[i] = cirt / cirs + ( stp <= cirt % cirs );
if ( stp % cirs == cirt % cirs ) f[0][0][i] = 1;//, printf ( "!%lld\n", i );
}
for ( int i = 1 % p, stp = 1; !onc[i] && stp <= n; i = suf[i], ++ stp ) {
buc[i] = 1;
if ( n == stp ) f[0][0][i] = 1;//, printf ( "!%lld\n", i );
}
} signed main () {
freopen ( "charge.in", "r", stdin );
freopen ( "charge.out", "w", stdout );
scanf ( "%lld %lld %lld", &n, &m, &p ), -- m;
for ( int i = 0; i < p; ++ i ) visc[i] = -1;
for ( int l = 1, sum = 1 % p, pwr = 10 % p; ; pwr = 10 * pwr % p, ++ l ) {
if ( ~visc[sum] ) { total ( sum, l ); break; }
visc[sum] = l, suf[sum] = ( sum + pwr ) % p;
if ( l == n ) { total ( sum, l ); break; }
sum = ( sum + pwr ) % p;
}
inv[1] = 1;
for ( int i = 2; i <= m; ++ i ) {
inv[i] = 1ll * ( MOD - MOD / i ) * inv[MOD % i] % MOD;
}
for ( int i = -1, sta = 0; i < p - 1; ++ i, sta ^= 1 ) {
for ( int j = 0; j <= m; ++ j ) {
for ( int k = 0; k < p; ++ k ) {
f[sta ^ 1][j][k] = 0;
}
}
for ( int k = 0; k < p; ++ k ) {
for ( int t = 0; t <= m; ++ t ) {
// 留意枚举的顺序,本质上是f(i,j,k)向后转移,
// 但这里统一计算了t相等时的组合数,再一起转移。
int c = 1;
for ( LL u = buc[i + 1] + t - 1, v = t; v; -- u, -- v ) {
c = 1ll * c * ( u % MOD ) % MOD * inv[v] % MOD;
}
for ( int j = 0; j + t <= m; ++ j ) {
addeq ( f[sta ^ 1][j + t][( k + ( i + 1 ) * t ) % p],
1ll * f[sta][j][k] * c % MOD );
}
}
}
}
int ans = 0;
for ( int i = 0; i <= m; ++ i ) addeq ( ans, f[p & 1][i][0] );
printf ( "%lld\n", ans );
return 0;
}

\(\mathcal{Details}\)

  面向数据编程 de 了好久 bug……DP 初值什么的一定不能想当然呐。

Solution -「LOCAL」充电的更多相关文章

  1. Solution -「LOCAL」二进制的世界

    \(\mathcal{Description}\)   OurOJ.   给定序列 \(\{a_n\}\) 和一个二元运算 \(\operatorname{op}\in\{\operatorname{ ...

  2. Solution -「LOCAL」大括号树

    \(\mathcal{Description}\)   OurTeam & OurOJ.   给定一棵 \(n\) 个顶点的树,每个顶点标有字符 ( 或 ).将从 \(u\) 到 \(v\) ...

  3. Solution -「LOCAL」过河

    \(\mathcal{Description}\)   一段坐标轴 \([0,L]\),从 \(0\) 出发,每次可以 \(+a\) 或 \(-b\),但不能越出 \([0,L]\).求可达的整点数. ...

  4. Solution -「LOCAL」Drainage System

    \(\mathcal{Description}\)   合并果子,初始果子的权值在 \(1\sim n\) 之间,权值为 \(i\) 的有 \(a_i\) 个.每次可以挑 \(x\in[L,R]\) ...

  5. Solution -「LOCAL」Burning Flowers

      灼之花好评,条条生日快乐(假装现在 8.15)! \(\mathcal{Description}\)   给定一棵以 \(1\) 为根的树,第 \(i\) 个结点有颜色 \(c_i\) 和光亮值 ...

  6. Solution -「LOCAL」画画图

    \(\mathcal{Description}\)   OurTeam.   给定一棵 \(n\) 个点的树形随机的带边权树,求所有含奇数条边的路径中位数之和.树形生成方式为随机取不连通两点连边直到全 ...

  7. Solution -「LOCAL」ZB 平衡树

    \(\mathcal{Description}\)   OurOJ.   维护一列二元组 \((a,b)\),给定初始 \(n\) 个元素,接下来 \(m\) 次操作: 在某个位置插入一个二元组: 翻 ...

  8. Solution -「LOCAL」舟游

    \(\mathcal{Description}\)   \(n\) 中卡牌,每种三张.对于一次 \(m\) 连抽,前 \(m-1\) 次抽到第 \(i\) 种的概率是 \(p_i\),第 \(m\) ...

  9. Solution -「LOCAL」「cov. 牛客多校 2020 第五场 C」Easy

    \(\mathcal{Description}\)   Link.(完全一致)   给定 \(n,m,k\),对于两个长度为 \(k\) 的满足 \(\left(\sum_{i=0}^ka_i=n\r ...

随机推荐

  1. Centos7 用户权限相关

    groups指的是多个用户组,一对多,test可能是其他用户组 /etc/passwd --记录系统用户信息文件 /etc/shadow --系统用户密码文件 /etc/group   --组用户记录 ...

  2. Linux上天之路(十)之Linux磁盘管理

    主要内容 磁盘介绍 磁盘管理 磁盘限额 逻辑卷管理 磁盘阵列 1. 磁盘介绍 硬盘最基本的组成部分是由坚硬金属材料制成的涂以磁性介质的盘片,不同容量硬盘的盘片数不等.每个盘片有两面,都可记录信息.盘片 ...

  3. 反射获取到class文件中的实例变量

    获取类的class 属性的三种方式 1.对象获取: 调用person类的父类方法getClaass(); Person p = new Person(); Class c = p.getClaass( ...

  4. 【Java】注解Annotation

    注解 Annotation 理解Annotation jdk 5.0 新增的功能 Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理.通 ...

  5. 【pwn】攻防世界 pwn新手区wp

    [pwn]攻防世界 pwn新手区wp 前言 这几天恶补pwn的各种知识点,然后看了看攻防世界的pwn新手区没有堆题(堆才刚刚开始看),所以就花了一晚上的时间把新手区的10题给写完了. 1.get_sh ...

  6. [STM32F4xx 学习] SPI与nRF24L01+的应用

    前面已经总结过STM32Fxx的特点和传输过程,下面以nRF24L01+ 2.4GHz无线收发器为例,来说明如何使用SPI. 一.nRF24L01+ 2.4GHz无线收发器的介绍 1. 主要特性 全球 ...

  7. 【机器学习】HMM

    机器学习算法-HMM 目录 机器学习算法-HMM 1. 模型定义 2. 序列生成 3. 概率计算 3.1 前向计算 3.2 后向计算 4. 学习 4.1 求解 4.2 求解 4.3 求解 5. 预测 ...

  8. 【失败经验分享】android下使用支持opencl的cv::dft()

    1.使用了UMat,但是并未使用GPU计算 cv::dft()函数的定义是: void cv::dft( InputArray _src0, OutputArray _dst, int flags, ...

  9. virtual studio发布到gihub

    问题 我们想要发布代码到github或者微软团队服务时候,往往发现没有本地库,所以难以发布. 解决方案 在解决方右击就可以新建git 文件都会出现小锁说明有了记录 文件夹会对应出现 右上角管理连接也会 ...

  10. HttpServletResponse接口详解

    在 Servlet API 中,定义了一个 HttpServletResponse 接口,它继承自 ServletResponse 接口.HttpServletResponse 对象专门用来封装 HT ...