[SCOI2007]排列

[SCOI2007]排列

标签:动态规划 状态压缩


题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:
7
000 1
001 1
1234567890 1
123434 2
1234 7
12345 17
12345678 29

输出样例#1:
1
3
3628800
90
3
6
1398

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

说明

100%的数据满足:s的长度不超过10, 1<=d<=1000, 1<=T<=15

题解

首先看到s很小,所以我们可以把s的状态压缩起来,题目还涉及是d的倍数,所以还需要一维记录余数。
设f[i][j]表示状态为i时余数为j的方案数。
那么每次枚举一个数,如果这个数没在i中出现过,就把他放到末尾(也可以放到首位,不过处理起来相对麻烦一些),并更新状态。

f[i | (1 << k)][(j * 10 + num[k]) % d] += f[i][j];

需要注意的是,因为数字有重复现象,所以我们最后答案要对每一个数字除以cnt[i]!
cnt[i]表示数字i出现的个数
当然这道题数据太小以至于可以用搜索。在此就不过多赘述了。

代码

#include<bits/stdc++.h>
#define N 2010
using namespace std;

char s[N];
int t, d;
int f[N][N], num[N], cnt[N];

int calc(int x)
{
    int ans = 1;
    for(int i = 1; i <= x; i ++) ans *= i;
    return ans;
}

int main()
{
    scanf("%d", &t);
    while(t --)
    {
        scanf("%s%d", s, &d);
        int len = strlen(s);
        memset(cnt, 0, sizeof(cnt));
        memset(f, 0, sizeof(f));
        f[0][0] = 1;
        for(int i = 0; i < len; i ++)
        {
            num[i] = s[i] - '0';
            cnt[s[i] - '0'] ++;
        }
        for(int i = 0; i < (1 << len); i ++)
            for(int j = 0; j <= d; j ++)
                for(int k = 0; k < len; k ++)
                    if(!(i & (1 << k)))
                       f[i | (1 << k)][(j * 10 + num[k]) % d] += f[i][j];
        for(int i = 0; i < 10; i ++)
            f[(1 << len) - 1][0] /= calc(cnt[i]);
        printf("%d\n", f[(1 << len) - 1][0]);
    } 
    return 0;
} 

心得

一般涉及倍数或者余数的问题,都要新开一维来记录状态。


  转载请注明: iSecloud's Blog [SCOI2007]排列

 上一篇
[AHOI2009]中国象棋 [AHOI2009]中国象棋
[AHOI2009]中国象棋标签: 动态规划 棋盘型 题目描述这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中
2019-07-09
下一篇 
邦邦的大合唱站队 邦邦的大合唱站队
邦邦的大合唱站队标签: 动态规划 状态压缩 题目描述$N(1<=N<=10^5)$个偶像排成一列,他们来自$M(1<=M<=20)$个不同的乐队。每个团队至少有一个偶像。 现在要求重新安排队列,使来自同一乐队的偶像
2019-07-08