题意:给定长度,然后从26个字母中选择n个来组成一个长为n的字符串,按照字典序标号为0,1,2.......,然后题目会给你字符串,求这个字符串的标号
题解:从m个字母中选择k个组成序列的放法数位P(m,k),从左往右依次填充,进行到第i个字母时,字典序小于该字母的元素还有cnt个,则说明它前面还有cnt个P(m,k),然后扫一遍出答案,由于n<=26,所以要高精度。
View Code
1 import java.util.*; 2 import java.math.*; 3 class Main 4 { 5 public static void main(String arg[]) 6 { 7 Scanner cin=new Scanner(System.in); 8 BigInteger f[][]=new BigInteger[30][30]; 9 BigInteger b[]=new BigInteger[30]; 10 b[0]=BigInteger.ONE; 11 for(int i=1;i<=26;i++) 12 b[i]=b[i-1].multiply(BigInteger.valueOf(i)); 13 f[0][0]=BigInteger.ONE; 14 for(int i=1;i<=26;i++) 15 { 16 f[i][0]=BigInteger.ONE; 17 for(int j=1;j<=i;j++) 18 f[i][j]=b[i].divide(b[i-j]); 19 } 20 while(true) 21 { 22 int n=cin.nextInt(); 23 if(n==0) 24 break; 25 String tp=cin.next(); 26 char s[]=tp.toCharArray(); 27 boolean mark[]=new boolean[30]; 28 Arrays.fill(mark, false); 29 BigInteger ans=BigInteger.ZERO; 30 for(int i=0,cnt,j,k;i<n;i++) 31 { 32 cnt=0; 33 k=s[i]-'A'; 34 mark[k]=true; 35 for(j=0;j<k;j++) 36 { 37 if(!mark[j]) 38 cnt++; 39 } 40 ans=ans.add(f[26-i-1][n-i-1].multiply(BigInteger.valueOf(cnt))); 41 } 42 System.out.println(ans); 43 } 44 } 45 }