<更新提示>

<第一次更新>


<正文>

Description

给定正整数n,m,问有多少个正整数满足:

(1) 不含前导0;

(2) 是m的倍数;

(3) 可以通过重排列各个数位得到n。

\(n\leq10^{20},m\leq100\)

Input Format

一行两个整数n,m。

Output Format

一行一个整数表示答案对998244353取模的结果。

Sample Input

1 1

Sample Output

1

解析

大致题意:给定一个位数不超过\(20\)位的正整数\(n\),求\(n\)的互异排列中有多少种情况恰为\(m\)的倍数,不能存在前导\(0\)。

假如\(n\leq10^{16},m\leq20\),那显然可以直接状压\(dp\)来计数,设\(f[S][i]\)代表\(n\)中取数情况为\(S\),得到的数模\(m\)余\(i\)的方案总数,可以枚举一个\(j\)来转移,时间复杂度\(O(2^{lg_n}lg_nm)\)。

当\(n\leq10^{20},m\leq100\)时,空间时间就都不行了。其实,在数字\(n\)中,很可能有多个一样的数字,而之前的状态我们把每一位数字都当做不一样的来处理,这样既费空间,又还需要额外判断重复状态。所以我们需要一种既能具体唯一表示状态,又不会有重复的状压方法。

对于这题来说,有一种很合适的状压方法:变进制状压。我们把\(0-9\)每一种数字各用了几次压成一个状态,例如\(0\)出现了一次,那么在状态中代表的权值就是\(1\),同理\(2\)个\(0\)代表的权值就是\(2\),假设有\(cnt_0\)个\(0\),那么权值就分别是\(1-cnt_0\),但是一个\(1\)代表的权值就是\(cnt_0+1\)了,一个\(1\)和一个\(0\)代表的权值是\(cnt_0+2\),两个\(1\)代表的权值是\(2cnt_0+1\),以此类推,这样可以以每一个数出现的次数来不重不漏地表示每一个状态。

显然,当每一个数字出现的次数尽可能平均时,代表的状态权值最大,实际测试可以发现最大权值不超过\(60000\),这样利用之前的转移方法就可以通过本题了,时间空间都没有问题。

\(Code:\)

#include <bits/stdc++.h>
using namespace std;
const int Mod = 998244353 , SIZE = 25 , Maxbit = 12 , M = 120 , MaxS = 60000;
char num[SIZE];
int m,len,cnt[Maxbit],f[MaxS][M];
int base[Maxbit],full[Maxbit],now[Maxbit];
inline void input(void)
{
scanf("%s",num+1);
len = strlen( num + 1 );
scanf("%d",&m);
}
inline void init(void)
{
for (int i=1;i<=len;i++)
cnt[ num[i] - '0' ] ++;
base[0] = 1 , full[0] = cnt[0];
for (int i=1;i<=9;i++)
{
base[i] = full[i-1] + 1;
full[i] = full[i-1] + base[i] * cnt[i];
}
}
inline void dp(void)
{
for (int i=1;i<=9;i++)
if ( cnt[i] )
f[base[i]][i%m] = 1;
for (int S=1;S<=full[9];S++)
{
int S_ = S;
for (int i=9;i>=0;i--)
if ( cnt[i] )
now[i] = cnt[i] - (S_/base[i]) , S_ %= base[i];
for (int i=0;i<=9;i++)
{
if ( !now[i] ) continue;
for (int j=0;j<m;j++)
{
int k = ( (j*10) % m + i ) % m;
f[ S + base[i] ][k] = ( f[ S + base[i] ][k] + f[S][j] ) % Mod;
}
}
}
}
int main(void)
{
input();
init();
dp();
printf("%d\n",f[full[9]][0]);
return 0;
}

<后记>

『数 变进制状压dp』的更多相关文章

  1. HDU 3001 Travelling 3进制状压dp

    题意:10个点,若干条边,边有花费,每个点最多走两次,求走过所有点,花费最少 分析:因为每个点最多走两次,所以联想到3进制,然后枚举状态,就行了(我也是照着网上大神的代码写的) #include &l ...

  2. T2963 贪吃蛇【BFS,四进制状压,A*】

    Online Judge:未知 Label:BFS,四进制状压,暴力,A*,哈希,玄学. 题目描述 给定一个n*m的地图和蛇的初始位置,地图中有些位置有石头,蛇不能经过.当然蛇也不能爬到地图之外. 每 ...

  3. ZRDay6A. 萌新拆塔(三进制状压dp)

    题意 Sol 这好像是我第一次接触三进制状压 首先,每次打完怪之后吃宝石不一定是最优的,因为有模仿怪的存在,可能你吃完宝石和他打就GG了.. 因此我们需要维护的状态有三个 0:没打 1:打了怪物 没吃 ...

  4. hdu 3001 Travelling 经过所有点(最多两次)的最短路径 三进制状压dp

    题目链接 题意 给定一个\(N\)个点的无向图,求从任意一个点出发,经过所有点的最短路径长度(每个点至多可以经过两次). 思路 状态表示.转移及大体思路 与 poj 3311 Hie with the ...

  5. HDU 3001 三进制状压DP

    N个城市,M条道路,每条道路有其经过的代价,每一个城市最多能够到达两次,求走全然部城市最小代价,起点随意. 三进制状压.存储每一个状态下每一个城市经过的次数. 转移方程: dp[i+b[k]][k]= ...

  6. 『Exclusive Access 2 dilworth定理 状压dp』

    Exclusive Access 2 Description 给出 N 个点M 条边的无向图,定向得到有向无环图,使得最长路最短. N ≤ 15, M ≤ 100 Input Format 第一行一个 ...

  7. UVA 10817 - Headmaster's Headache(三进制状压dp)

    题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=20&pag ...

  8. Travelling (三进制+状压dp)

    题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read(){ ,f= ...

  9. HDU - 3001 Travelling(三进制状压dp)

    Travelling After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best ch ...

随机推荐

  1. Atlassian JIRA服务器模板注入漏洞复现(CVE-2019-11581)

    0x00 漏洞描述 Atlassian Jira是澳大利亚Atlassian公司的一套缺陷跟踪管理系统.该系统主要用于对工作中各类问题.缺陷进行跟踪管理. Atlassian Jira Server和 ...

  2. ASP.NET Core MVC 502 bad gateway 超时如何处理

    在网页程序运行需要较长时间运行的时候,ASP.NET Core MVC会出现502 bad gateway请求超时情况.一般默认的超时时间都比较短,我们需要在 web.config 中配置一下.其中  ...

  3. windows系统DOC命令启动或停止服务

    -- 启动服务 -- net start Mysql -- 停止服务 -- net stop Mysql-- 说明:MysqL没有大小写区分.可以直接小写mysql. -- 启动报错(net star ...

  4. 03、磁盘管理+swap分区创建+磁盘配额+自动挂载

    磁盘管理 分区标识 一般用4位标识,前两位,磁盘类型,第3位,磁盘编号,第4位,分区编号 如: /dev/sda1     sd  磁盘类型    a  磁盘编号   1  分区编号 [root@s1 ...

  5. Linux中一些命令的区别

    1. yum provides 和 yum search provides是在文件中查找软件,类似于rpm -qf: search是查找软件包或其描述的关键字. 2. gzip  和  bzip2 对 ...

  6. 通过ALTER DATABASE postgres SET 解决 plv8 plv8.start_proc 问题

    通过plv8.start_proc 我们可以使用类似钩子的改变 ,方便的扩展plv8,比如基于plv8.start_proc 的require 实现 命令 ALTER DATABASE postgre ...

  7. IDEA中各种图标

    前言 在用这个开发工具之前对大量的图标先有所了解,会提高不少效率 首先讲下基本的图标     Java类 Java抽象类 Groovy类 注解类 枚举类 异常类 最终的类 接口 包含有main方法的可 ...

  8. [RN] React Native 定义全局变量

    React Native 定义全局变量 React Native全局变量的两种使用方式 一.导出和导入 // 定义的页面 global.js var global = {authorization: ...

  9. 第08组 Beta冲刺(3/5)

    队名:955 组长博客:点这里! 作业博客:点这里! 组员情况 组员1(组长):庄锡荣 过去两天完成了哪些任务 文字/口头描述 ? 维持进度,检查需求 展示GitHub当日代码/文档签入记录 接下来的 ...

  10. udev只能修改Linux 网口名称,无法修改/dev目录下的设备名称

    NAME The name to use for a network interface. The name of a device node cannot be changed by udev, o ...