bzoj 1072 排列perm

题目大意:

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

思路:

早上棒神告诉我一道状压dp

我看了看数据感觉可以next_permutation+map艹过去

结果发现这种时候map太辣鸡T掉了

然后换了set

然后,然后就艹过去了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #include<set>
10 #define inf 2139062143
11 #define ll long long
12 #define MAXN 105
13 using namespace std;
14 inline int read()
15 {
16     int x=0,f=1;char ch=getchar();
17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
19     return x*f;
20 }
21 ll T,k,n,a[11],p,ans;
22 set <ll> s;
23 int main()
24 {
25     T=read();
26     while(T--)
27     {
28         char ch[11];scanf("%s",ch);k=read();
29         s.clear();
30         n=strlen(ch);ans=0;
31         for(int i=0;i<n;i++) a[i]=ch[i]-'0';
32         sort(a,a+n);
33         do
34         {
35             p=a[0];
36             for(int i=1;i<n;i++) p=p*10+a[i];
37             if(p%k==0&&!s.count(p)) {ans++;s.insert(p);}
38         }
39         while(next_permutation(a,a+n));
40         printf("%d\n",ans);
41     }
42 }
View Code

晚上回家觉得自己太菜

还是写一下状压dp

然后就搞了一下

dp i j 表示用了i位(压缩后) 除d余j的方案数

然后就可以愉快的转移了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #define inf 2139062143
11 #define ll long long
12 #define MAXN
13 #define MOD
14 using namespace std;
15 inline int read()
16 {
17     int x=0,f=1;char ch=getchar();
18     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
19     while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
20     return x*f;
21 }
22 int p,dp[1030][1010],n,T,cnt[15],a[15];
23 int main()
24 {
25     T=read();
26     while(T--) 
27     {
28         memset(dp,0,sizeof(dp));
29         memset(cnt,0,sizeof(cnt));
30         char ch[15];scanf("%s",ch);n=strlen(ch),dp[0][0]=1,p=read();
31         for(int i=0;i<n;i++) a[i]=ch[i]-'0',cnt[a[i]]++;
32         for(int i=0;i<(1<<n);i++)
33             for(int j=0;j<p;j++)
34                 for(int k=0;k<n;k++)
35                     if(!(i&(1<<k))) dp[i|(1<<k)][(j*10+a[k])%p]+=dp[i][j];
36         int ans=dp[(1<<n)-1][0];
37         for(int i=0;i<=9;i++)
38             for(int j=1;j<=cnt[i];j++) ans/=j;
39         printf("%d\n",ans);
40     }
41 }
View Code
posted @ 2018-01-31 20:05  jack_yyc  阅读(149)  评论(0编辑  收藏  举报