排列(STL函数运用/状压dp)

题目描述

给一个数字串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整除的排列的个数。

样例

样例输入

7
000 1
001 1
1234567890 1
123434 2
1234 7
12345 17
12345678 29

样例输出

1
3
3628800
90
3
6
1398

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

 方法一:状压dp状态转移

#include <bits/stdc++.h>
using namespace std;
const int maxn=1<<10;
int d,len,dp[maxn<<1][maxn],c[maxn],a[maxn];
char s[15];
int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        memset(dp,0,sizeof(dp));
        scanf("%s",s);
        len=strlen(s);
        scanf("%d",&d);
        for(int i=0;i<len;i++) a[i+1]=s[i]-'0';
        int Maxn=(1<<len)-1;
        dp[0][0]=1;
        for(int s=0;s<=Maxn;s++) {
            memset(c,0,sizeof(c));
            for(int i=1;i<=len;i++) {
                if(!(s&(1<<(i-1)))&&!c[a[i]]) {
                    c[a[i]]=1;
                    for(int j=0;j<d;j++) {
                        dp[s|(1<<(i-1))][(j*10+a[i])%d]+=dp[s][j];//dp[s][j](s为选的数字状态的压缩,选的几个数字取模后余j)的方案数
                    }
                }
            }
        }
        printf("%d
",dp[Maxn][0]);
    }
    return 0;
}

方法二:STL全排列函数

用STL库中的全排列函数的解法(自带判重加修改)

next_permutation从递增数列求出全排列组合(从小到大);

相反函数:prev_permutation(从大到小)

全排列讲解:https://blog.csdn.net/qq_26849233/article/details/73951266

然后运用函数暴力枚举全排列,计算个数;

#include <bits/stdc++.h>
using namespace std;
inline int read(){
    int x = 0, w = 1;
    char ch = getchar();
    for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
    for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
    return x * w;
}

const int maxn = 5200;
char ch[maxn];
int a[maxn];

signed main(){
    int t = read();
    int ans = 0;
    while(t--){
        cin >> ch;
        int n = read();
        int len = strlen(ch);
        for(int i = 0; i < len; i++){
            a[i + 1] = ch[i] - '0';
        }
        sort(a + 1, a + 1 + len);
        ans = 0;
        do{
            int tmp = 0;
            for(int i = 1 ;i <= len; i++)
                tmp = tmp * 10 + a[i];
            if(tmp % n == 0) ans++;
        }while(next_permutation(a + 1, a + 1 + len));
        cout << ans << endl;
    }
    return 0;
}

 午歌:apologize

原文地址:https://www.cnblogs.com/1999-09-21Karry-erfs/p/13197731.html