LightOJ-1060-dfs,组合数学

来源:互联网 发布:网络服务公司是干嘛的 编辑:程序博客网 时间:2024/05/29 15:08

题目大意:给一段字符串,可以任意将其中两个字符进行交换,问最后所有的情况中按字典序排序的第k中情况是多少,如果没有就输出impossible;

题目解析:按位枚举,从高位枚举,如果在当前位置后面的情况>=k,说明那个位肯定是正确的了,再枚举下一位,反之,将当前为的cur+1;

AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>using namespace std;typedef long long ll;ll fact[21];int cnt[26];char s[23];void init(){fact[0]=fact[1]=1;int i;for(i=2;i<=20;i++)fact[i]=fact[i-1]*i;}ll calu(){ll t=1;int i,cntt=0;for(i=0;i<26;i++){cntt+=cnt[i];t*=fact[cnt[i]];}return fact[cntt]/t;}bool dfs(int pos,int cur,int ans){if(!cnt[cur])return dfs(pos,cur+1,ans);if(pos>=strlen(s+1)||cur>=26)return 1;int i;cnt[cur]--;ll temp=calu();if(temp>=ans){printf("%c",'a'+cur);dfs(pos+1,0,ans);}else {ans-=temp;cnt[cur]++;dfs(pos,cur+1,ans);}}int main(){int cas,c,n,i;scanf("%d",&cas);init();for(c=1;c<=cas;c++){memset(cnt,0,sizeof(cnt));scanf("%s",&s[1]);scanf("%d",&n);for(i=1;i<=strlen(s+1);i++)cnt[s[i]-'a']++;if(n>calu()){printf("Case %d: Impossible\n",c);continue;}printf("Case %d: ",c);dfs(0,0,n);printf("\n"); }return 0;}



0 0
原创粉丝点击