LightOJ1021-Painful Bases-状态压缩

    xiaoxiao2023-03-24  4

    题目大意:给你一段序列,并告诉你是几进制的,问你这段序列的全排列能够整除k的有几个;

    题目解析:状态dp中的序列肯定与顺序无关,但乍一看这道题目的序列是有顺序的,但仔细一想,我们只需要自定义它入序列的顺序就可以了,可以规定每次都在最高位加入,也可以规定每次都在最低位加入,这样很状态dp了,dp的时候也很简单,老套路枚举即可;

    //但我真的很想吐槽下LightOJ为什么__int64不可以一定要long long,调了1h的无聊bug,终于发现这个问题后,再也不想上LightOJ了。

    AC代码:

    #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #define ll long long using namespace std; int b,k; ll dp[(1<<16)+10][25]; int fun(int s) { int sum=0,i; for(i=0;i<b;i++) { if(s&(1<<i)) { sum++; } } return sum; } int main() { int i,j,l,num,mod[25],x[25],len,cas,c; string str; cin>>cas; for(c=1;c<=cas;c++) { scanf("%d%d",&b,&k); memset(dp,0,sizeof(dp)); cin>>str; num=0; for(i=0;i<str.length();i++) { if(str[i]>'9'||str[i]<'0') { x[i]=10+str[i]-'A'; } else { x[i]=str[i]-'0'; } num++; } len=1<<num; mod[0]=1%k; mod[1]=b%k; for(i=2;i<num;i++) { mod[i]=(mod[1]*mod[i-1])%k; } dp[0][0]=1; for(i=0;i<len;i++) { for(j=0;j<num;j++) { if(i&(1<<j)) continue; else { for(l=0;l<k;l++) { dp[i|(1<<j)][(l+x[j]*mod[fun(i)])%k]+=dp[i][l]; } } } } printf("Case %d: %lld\n",c,dp[len-1][0]); } return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-1201726.html
    最新回复(0)