排列

Time Limit: 10 Sec  Memory Limit: 128 MB
[Submit][Status][Discuss]

Description

  给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0)。

  例如123434有90种排列能被2整除,其中末位为2的有30种,末位为4的有60种。

Input

  输入第一行是一个整数T,表示测试数据的个数,以下每行一组s和d,中间用空格隔开。

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

  s的长度不超过10, 1<=d<=1000, 1<=T<=15

Solution

  我们运用状压DP,令 f[j][opt] 表示当前余数为 j,状态为opt的方案

  状态记录的是:各个数字被用了几次。

  那么我们就可以状压了。先DFS出每个状态,记sum[k]表示后缀积,那么显然 从 opt 转移到 第k个数字多用一次的状态 就是 opt + sum[k + 1]

Code

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long s64; const int ONE = ; int T, n, m;
int num;
int vis[ONE], Num[], sum[];
int f[][];
int Sta[ONE][];
char ch[ONE]; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} void Dfs(int T)
{
if(T > )
{
num++;
for(int i = ; i <= ; i++)
Sta[num][i] = vis[i];
return;
} for(int i = ; i <= Num[T]; i++)
vis[T] = i, Dfs(T + );
} void Deal()
{
memset(f, , sizeof(f));
memset(Num, , sizeof(Num));
memset(sum, , sizeof(sum));
num = ;
scanf("%s", ch + ); m = get();
n = strlen(ch + ); for(int i = ; i <= n; i++) Num[ch[i] - '']++;
sum[] = ; for(int i = ; i >= ; i--) sum[i] = sum[i + ] * (Num[i] + ); Dfs(); f[][] = ;
for(int opt = ; opt <= num; opt++)
for(int j = ; j < m; j++)
if(f[j][opt])
for(int k = ; k <= ; k++)
{
if(Sta[opt][k] >= Num[k]) continue;
int to = opt + sum[k + ];
f[(j * + k) % m][to] += f[j][opt];
} printf("%d\n", f[][num]);
} int main()
{
T = get();
while(T--)
Deal();
}

【BZOJ1072】【SCOI2007】排列 [状压DP]的更多相关文章

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

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

  2. BZOJ1072 排列perm 【状压dp】

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

  3. B1072 [SCOI2007]排列perm 状压dp

    很简单的状压dp,但是有一个事,就是...我数组开大了一点,然后每次memset就会T,然后开小就好了!!!震惊!以后小心点这个问题. 题干: Description 给一个数字串s和正整数d, 统计 ...

  4. 暑假集训Day 4 P4163 [SCOI2007]排列 (状压dp)

    状压dp (看到s的长度不超过10就很容易想到是状压dp了 但是这个题的状态转移方程比较特殊) 题目大意 给一个数字串 s 和正整数 d, 统计 s 有多少种不同的排列能被 d 整除(可以有前导 0) ...

  5. 排列perm HYSBZ - 1072(状压dp/暴力)

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

  6. 「状压DP」「暴力搜索」排列perm

    「状压DP」「暴力搜索」排列 题目描述: 题目描述 给一个数字串 s 和正整数 d, 统计 sss 有多少种不同的排列能被 d 整除(可以有前导 0).例如 123434 有 90 种排列能被 2 整 ...

  7. 状压DP之LGTB 与序列

    题目 思路 这道题竟然是状压DP,本人以为是数论,看都没看就去打下一题的暴力了,哭 \(A_i\)<=30,所以我们只需要考虑1-58个数,再往后选的话还不如选1更优,注意,1是可以重复选取的, ...

  8. HDU5816 Hearthstone(状压DP)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5816 Description Hearthstone is an online collec ...

  9. jzoj 5230 队伍统计(状压DP)

    Description 现在有n个人要排成一列,编号为1->n .但由于一些不明原因的关系,人与人之间可能存在一些矛盾关系,具体有m条矛盾关系(u,v),表示编号为u的人想要排在编号为v的人前面 ...

随机推荐

  1. Notes of the scrum meeting before publishing(12.17)

    meeting time:18:30~20:30p.m.,December 17th,2013 meeting place:3号公寓一层 attendees: 顾育豪                  ...

  2. 解决python中文编码错误问题

    对于初学者而言,编码问题或许还没有没重视起来,但是编码问题是中文开发者必须面对的.今天来看下python开发中如何解决编码问题.注意:本篇讲的是最常见的一种编码问题,其他编码问题,如json函数引起的 ...

  3. 【week2】 构建之法 读后感及问题

    上一次读后感涵盖前五章的内容包括个人技术,结对合作,小组项目等.本周作业的燃尽图以及站立会议是关于<构建之法>第六章的内容,所以关于这一章的读后感涵盖在上两篇博客中. 第七章 MSF 介绍 ...

  4. extract函数行结果

    $arr2=array('a'=>'aaaa','b'=>'bbbb','c'=>'cccc','d'=>'dddd','e'=>'eeeee','b'=>'fff ...

  5. OO的五大原则

    OO的五大原则是指SRP.OCP.LSP.DIP.ISP 1. SRP(Single Responsibility Principle 单一职责原则) 单一职责很容易理解,所谓单一职责,就是一个设计元 ...

  6. Android基础------SQLite数据库(一)

    1.SQLite介绍 SQLite是一款非常流行的嵌入式数据库,它支持SQL操作,并且只用很少的内存. Android在运行时集成了SQLite,所有每个Android应用程序都可以使用SQLLite ...

  7. SpringBoot使用servletAPI与异常处理

    工程结构: 主方法类: package com.boot.servlet.api.bootservlet; import org.springframework.boot.SpringApplicat ...

  8. 【bzoj2699】更新 dp

    题目描述 对于一个数列A[1..N],一种寻找最大值的方法是:依次枚举A[2]到A[N],如果A[i]比当前的A[1]值要大,那么就令A[1]=A[i],最后A[1]为所求最大值.假设所有数都在范围[ ...

  9. Python十六进制转码问题

    使用Python的decode函数转码十六进制的字符串时,会出现UnicodeDecodeError: 'utf8' codec can't decode byte 0xba in position ...

  10. (转)超详细单机版搭建hadoop环境图文解析

                        超详细单机版搭建hadoop环境图文解析   安装过程: 一.安装Linux操作系统 二.在Ubuntu下创建hadoop用户组和用户 三.在Ubuntu下安装 ...