标签:字符串 数字 初始 eof -- 中间 line size 超过
[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整除的排列的个数。
7
000 1
001 1
1234567890 1
123434 2
1234 7
12345 17
12345678 29
1
3
3628800
90
3
6
1398
在前三个例子中,排列分别有1, 3, 3628800种,它们都是1的倍数。
100%的数据满足:s的长度不超过10, 1<=d<=1000, 1<=T<=15。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1<<11,maxm=1000+10;
int f[maxn][maxm];//f[i][j]表示状态i余数为j的排序个数
int T,mod;
int a[maxn],cnt[maxn];//cnt记录某个数i出现的次数
char s[15];
int J[]={0,1,2,6,24,120,720,5040,40320,362880,3628800};
int main(){
scanf("%d",&T);
while(T--){
memset(cnt, 0, sizeof(cnt));//一定记得初始化
memset(f, 0, sizeof(f));
scanf("%s%d",s,&mod);
int len=strlen(s);
for(int i=0;i<len;i++){
a[i+1]=s[i]-‘0‘;
cnt[a[i+1]]++;//记录a[i+1]出现次数
}
int lim=1<<len;//记录界限
f[0][0]=1;//初始化临界状态,0状态下余数为0的有1种情况
for(int i=0;i<lim;i++){//枚举状态
for(int k=0;k<mod;k++){//枚举余数
if(f[i][k]){//假如没有跳过
for(int j=0; j<len; j++)//枚举插入的数字
if( (i & (1<<j)) == 0 )//无交集
f[(i|(1<<j))][(k*10+a[j+1])%mod] += f[i][k];//叠加
}
}
}
int ans=f[lim-1][0];
for(int i=0; i<=9; i++) if( cnt[i] ) ans /= J[cnt[i]];//去重
cout<<ans<<endl;
}
}
标签:字符串 数字 初始 eof -- 中间 line size 超过
原文地址:https://www.cnblogs.com/soda-ma/p/13196026.html