小易在学校中学习了关于字符串的理论, 于是他基于此完成了一个字典的项目。
小易的这个字典很奇特, 字典内的每个单词都包含n个'a'和m个'z', 并且所有单词按照字典序排列。
小易现在希望你能帮他找出第k个单词是什么。
小易在学校中学习了关于字符串的理论, 于是他基于此完成了一个字典的项目。
小易的这个字典很奇特, 字典内的每个单词都包含n个'a'和m个'z', 并且所有单词按照字典序排列。
小易现在希望你能帮他找出第k个单词是什么。
输入包括一行三个整数n, m, k(1 <= n, m <= 100, 1 <= k <= 109), 以空格分割。
输出第k个字典中的字符串,如果无解,输出-1。
2 2 6
zzaa
字典中的字符串依次为aazz azaz azza zaaz zaza zzaa
思路: a..a z..z n个a和m个z, 设C(n,m)表示总的排列个数 那么C(n,m)有两种情况 y以a为开头的和以z为开头的 我们可以得到递推式 C(n, m) = C(n-1, m) + C(n,m-1) C(0,0) = 0, C(n,0) = 1, C(0,m)=1 可以算出矩阵C 因为是按照字典排序,所以a在前,z在后 我们考虑第k个字符串的首位,C(n-1,m)位之前都是a,之后都是z 只要k和C(n-1,m)比较就可以知道首位了, 去掉第一位后,我们可以得到剩下n+m-1字符串的位置,重复前面的过程 import java.io.BufferedInputStream; import java.math.BigInteger; import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner cin = new Scanner(new BufferedInputStream(System.in)); int n,m,k; n = cin.nextInt(); m = cin.nextInt(); k = cin.nextInt(); BigInteger[][] c = new BigInteger[n+1][m+1]; for(int i=0;i<=n;i++){ c[i][0] = BigInteger.ONE; } for(int i=0;i<=m;i++){ c[0][i] = BigInteger.ONE; } c[0][0]=BigInteger.ZERO; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ c[i][j] = c[i-1][j].add(c[i][j-1]); } } if(BigInteger.valueOf(k).compareTo(c[n][m])>0){ System.out.println("-1"); return; } int cn, cm,ck; cn = n; cm = m; ck = k; StringBuilder sb = new StringBuilder(n+m); for(int i=0;i< n+m; i++){ BigInteger t = c[cn-1][cm]; // if(ck <=t) { if(BigInteger.valueOf(ck).compareTo(t)<=0) { sb.append("a"); cn--; }else{ sb.append("z"); ck-=t.longValue(); cm--; } if(cn==0){ for (int j = 0; j < cm; j++) { sb.append("z"); } break; } if(cm==0){ for (int j = 0; j < cn; j++) { sb.append("a"); } break; } } System.out.println(sb.toString()); } }
顶我上去,全场最好理解
1.n个'z'和m个‘a’组成的组合数的关系
dp[i][j]=dp[i-1][j]+dp[i][j-1]
2.关于找第几个的问题,递归
固定右边x位,从m-1个z开始固定,a的个数逐渐增加
刚好没有进入下一层递归,就应该是aaazz..zzaaa这种形式
如果不是k不是刚好减去就应该是aa...aazxxxxx后面就进入xxxx里面再做一层递归
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc=new Scanner(System.in); int n=sc.nextInt(); int m=sc.nextInt(); int k=sc.nextInt(); long[][] dp=new long[101][101]; //dp[i][j]i个'a'和j个'b'的组合数 for(int i=0;i<101;i++) dp[i][0]=1; for(int j=1;j<101;j++) dp[0][j]=1; for(int i=1;i<101;i++) { for(int j=1;j<101;j++) { dp[i][j]=dp[i-1][j]+dp[i][j-1]; } } if(dp[n][m]<k) { System.out.println("-1"); return; } Main main=new Main(); StringBuilder sb=new StringBuilder(); main.solve(n, m, k, sb, dp); } public void solve(int a,int z,int k,StringBuilder sb,long[][] dp) { if(a==0) { for(int i=0;i<z;i++) sb.append("z"); System.out.println(sb.toString()); return; } if(z==0) { for(int i=0;i<a;i++) sb.append("a"); System.out.println(sb.toString()); return; } int la=0,lz=z-1; while(k-dp[la][lz]>=0) { k-=dp[la][lz]; la++; } if(k==0) { for(int i=0;i<a-la+1;i++) sb.append("a"); for(int i=0;i<z;i++) sb.append("z"); for(int i=0;i<la-1;i++) sb.append("a"); System.out.println(sb.toString()); return; } for(int i=0;i<a-la;i++) sb.append("a"); sb.append("z"); solve(la,lz,k,sb,dp); } }