bzoj1072 [SCOI2007]排列perm

来源:互联网 发布:有多少网络交易平台 编辑:程序博客网 时间:2024/05/19 03:17

题目

令人窒息的一道(shui)题。
纯暴力地考虑。
用next_permutation求下一个排列,set去重。这样可是能过的呀。

    scanf("%d\n",&T);    while(T--)    {        scanf("%s",s);scanf("%d\n",&p);        len=strlen(s);        for(int i=1;i<=len;i++)A[i]=s[i-1]-'0';        sort(A+1,A+len+1);        ans=0;        E.clear();        while(1)        {            num=0;            for(int i=1;i<=len;i++)num=(long long)num*10+A[i];            if(E.count(num)==0&&num%p==0)            {                ans++;                E.insert(num);            }            if(!next_permutation(A+1,A+len+1))break;        }        printf("%d\n",ans);    }

妙吧。。。

不过,还有正常的方法的。。

状压dp,f[i][j],状态为i时,余数为j的方案数。

转移。

但是,这样会有重复的。

感性认知,当一个数出现了n次时,答案除以一个n的阶乘就好了。

#include<bits/stdc++.h>using namespace std;int T,A[15],len,p,ans;char s[15]; set <long long> E;long long num;int f[1030][1005]; int cnt[10];inline char nc(){    static char buf[100000],*p1=buf,*p2=buf;    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline int read(){    int x=0,b=1;    char c=nc();    for(;!(c<='9'&&c>='0');c=nc())if(c=='-')b=-1;    for(;c<='9'&&c>='0';c=nc())x=x*10+c-'0';    return x*b;}inline void write(int x){    if(x==0)putchar('0');    else    {        char buf[15];        int len=0;        if(x<0)putchar('-'),x=-x;        while(x)buf[++len]=x%10+'0',x/=10;        for(int i=len;i>=1;i--)putchar(buf[i]);    }    putchar('\n');}int main(){    freopen("in.txt","r",stdin);/*---------------------------暴力-----------------------------*///  scanf("%d\n",&T);//  while(T--)//  {//      scanf("%s",s);scanf("%d\n",&p);//      len=strlen(s);//      for(int i=1;i<=len;i++)A[i]=s[i-1]-'0';//      sort(A+1,A+len+1);//      ans=0;//      E.clear();//      while(1)//      {//          num=0;//          for(int i=1;i<=len;i++)num=(long long)num*10+A[i];//          if(E.count(num)==0&&num%p==0)//          {//              ans++;//              E.insert(num);//          }//          if(!next_permutation(A+1,A+len+1))break;//      }//      printf("%d\n",ans);//  }/*---------------------------暴力-----------------------------*/    scanf("%d\n",&T);    while(T--)    {        scanf("%s%d\n",s,&p);        len=strlen(s);        memset(cnt,0,sizeof(cnt));         for(int i=1;i<=len;i++)A[i]=s[i-1]-'0';        for(int i=1;i<=len;i++)cnt[A[i]]++;        memset(f,0,sizeof(f));        f[0][0]=1;        for(int i=0;i<=(1<<len)-1;i++)            for(int j=0;j<p;j++)                for(int k=1;k<=len;k++)                    if((i&(1<<(k-1)))==0)                        f[i|(1<<(k-1))][(j*10+A[k])%p]+=f[i][j];        ans=f[(1<<len)-1][0];        for(int i=0;i<=9;i++)            for(int j=1;j<=cnt[i];j++)                ans/=j;        printf("%d\n",ans);    }    return 0;}
原创粉丝点击