Description

给一个数字串\(s\)和正整数\(d\), 统计\(s\)有多少种不同的排列能被\(d\)整除(可以有前导\(0\))。例如\(123434\)有\(90\)种排列能被\(2\)整除,其中末位为\(2\)的有\(30\)种,末位为\(4\)的有\(60\)种。

Input

输入第一行是一个整数\(T\),表示测试数据的个数,以下每行一组\(s\)和\(d\),中间用空格隔开。\(s\)保证只包含数字\(0, 1, 2, 3, 4, 5, 6, 7, 8, 9\).

Output

每个数据仅一行,表示能被\(d\)整除的排列的个数。

Sample Input

7

000 1

001 1

1234567890 1

123434 2

1234 7

12345 17

12345678 29

Sample Output

1

3

3628800

90

3

6

1398

HINT

在前三个例子中,排列分别有\(1, 3, 3628800\)种,它们都是\(1\)的倍数。

\(100\%\)的数据满足:\(s\)的长度不超过\(10\),$ 1 \le d \le 1000, 1 \le T \le 15$

\(f[i][j]\)表示状态为\(i\)(用二进制表示,若某位为\(1\),则该位在排列中)余数为\(j\)的方案数。于是,我们可以枚举排列长度,利用已知排列进行转移(应该很好YY,脑补一下)。代码应该好理解。

#include<vector>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std; #define maxn (12)
#define maxm (1010)
char s[maxn]; int n,m,f[1<<maxn][maxm],mi[maxn],jie[maxn]; vector <int> vec[maxn]; inline void dfs(int now,int bin,int have)
{
if (now > n) { vec[have].push_back(bin); return; }
dfs(now+1,bin<<1|1,have+1); dfs(now+1,bin<<1,have);
} inline void dp()
{
for (int i = 0;i <= n;++i) vec[i].clear();
dfs(1,0,0);
mi[0] = 1;
for (int i = 1;i <= n;++i) mi[i] = 10*mi[i-1]%m;
memset(f,0,sizeof(f));
for (int i = 1;i <= n;++i) f[1<<(i-1)][(s[i]-'0')%m] = 1;
for (int i = 2;i <= n;++i)
{
int ni = vec[i].size();
for (int ii = 0;ii < ni;++ii)
{
int p = vec[i][ii];
for (int j = 1;j <= n;++j)
if (p & (1<<(j-1)))
{
int q = p^(1<<(j-1));
for (int k = 0;k < m;++k)
f[p][(k+mi[i-1]*(s[j]-'0')%m)%m] += f[q][k];
}
}
}
for (int i = '0';i <= '9';++i)
{
int cnt = 0;
for (int j = 1;j <= n;++j) cnt += s[j] == i;
f[(1<<n)-1][0] /= jie[cnt];
}
} int main()
{
freopen("1072.in","r",stdin);
freopen("1072.out","w",stdout);
jie[0] = 1;
for (int i = 1;i <= 10;++i) jie[i] = i*jie[i-1];
int T; scanf("%d\n",&T);
while (T--)
{
scanf("%s %d\n",s+1,&m); n = strlen(s+1);
dp(); printf("%d\n",f[(1<<n)-1][0]);
}
fclose(stdin); fclose(stdout);
return 0;
}

BZOJ 1072 排列的更多相关文章

  1. [BZOJ 1072] 排列perm

    Link: BZOJ 1072 传送门 Solution: 一道直接next_permutation纯暴力就能过的题? 难道2007年时大家都不知道next_permutation这个函数吗 还是用复 ...

  2. [BZOJ 1072] [SCOI2007] 排列perm 【状压DP】

    题目链接:BZOJ 1072 这道题使用 C++ STL 的 next_permutation() 函数直接暴力就可以AC .(使用 Set 判断是否重复) 代码如下: #include <io ...

  3. BZOJ 1072: [SCOI2007]排列perm 状态压缩DP

    1072: [SCOI2007]排列perm Description 给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0).例如123434有90种排列能被2整除,其中末位为 ...

  4. BZOJ 1072 [SCOI2007]排列perm

    1072: [SCOI2007]排列perm Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1268  Solved: 782[Submit][Sta ...

  5. BZOJ 1072: [SCOI2007]排列perm [DP 状压 排列组合]

    题意:给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0) 100%的数据满足:s的长度不超过10, 1<=d<=1000, 1<=T<=15 看到整 ...

  6. 【以前的空间】bzoj 1072 [SCOI2007]排列perm

    又颓废了一个下午,最近撸mc撸到丧失意识了,玩的有点恶心,于是找水题做,瞧不起颓废的自己啊. another水题. 这题题意很明显啦,就是找数字排列后组成的数去mod d=0后有多少种. 普通的搜索的 ...

  7. 【62.89%】【BZOJ 1072】[SCOI2007]排列perm

    Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1862  Solved: 1171 [Submit][Status][Discuss] Descri ...

  8. BZOJ 1072 [SCOI2007]排列perm ——状压DP

    [题目分析] 没什么好说的,水题. 代码比较丑,结果需要开long long 时间爆炸 [代码] #include <cstdio> #include <cstring> #i ...

  9. bzoj 1072: [SCOI2007]排列perm【状压dp】

    先写了个next_permutation结果T了,于是开始写状压 设f[s][i]为选取状态为s,选的数模d为i的方案数,去重的话直接除以每个数字的出现次数的阶乘即可 #include<iost ...

随机推荐

  1. 关于PHP程序使用file_get_content()函数进行抓取PHP程序与smarty结合编译过程中产生的静态文件,抓取不了?连接超时?(地址映射)

    问题: 当file_get_content()函数的参数  url中是localhost时不能抓取,是127.0.0.1时可以抓取到静态html代码.实现页面静态化技术提高访问效率. test.php ...

  2. System.in与System.out(标准输入与标准输出)详解

    package test; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; p ...

  3. 摄像头参数查看与调节 分类: C/C++ OpenCV 2014-11-08 18:13 138人阅读 评论(0) 收藏

    cvGetCaptureProperty 获得视频获取结构的属性 double cvGetCaptureProperty( CvCapture* capture, int property_id ); ...

  4. Android 手动显示和隐藏软键盘

    1.方法一(如果输入法在窗口上已经显示,则隐藏,反之则显示) InputMethodManager imm = (InputMethodManager) getSystemService(Contex ...

  5. Qt 学习之路:Qt 简介

    Qt 是一个著名的 C++ 应用程序框架.你并不能说它只是一个 GUI 库,因为 Qt 十分庞大,并不仅仅是 GUI 组件.使用 Qt,在一定程度上你获得的是一个“一站式”的解决方案:不再需要研究 S ...

  6. Android 6.0 双卡拨号

    相关 api getCallCapablePhoneAccountsAdded in API level 23 Android 5.0 之前的版本 Call from second sim 获取 si ...

  7. Java——(一)一切都是对象

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.用引用操纵对象   在java中一切都被视为对象,但操纵的标识符实际上是对象的一个“引用”( ...

  8. iOS 数据持久化(1):属性列表与对象归档

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css); @import url(/ ...

  9. oracle过滤分割字符串自定义函数

    该函数实现过滤前后的指定的字符串,诸如过滤分隔符等.可用于过滤字符串中的逗号分割符.特别说明:substr()函数支持从字符串倒数开始读取,例如: dbms_output.put_line( subs ...

  10. Python之路【第五篇】:面向对象和相关

    Python之路[第五篇]:面向对象及相关   面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...