后缀数组+贪心+隔板法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Littlewhite520/article/details/79326138

题意:给你sa数组,就是每个排名的后缀开始下标,让你求有多少种满足要求的串,有那么一个原理,对于相邻排名的两个后缀,后缀i的首字母要不要大于i-1,的取决于,第二个字符的比较,如果i的第二个字符>i-1的,那么i的首字符必然要+1,每一个后缀只要比较第二个字符就好,因为别的都会遍历到,这个是
if(ra[sa[i]+1]>ra[sa[i+1]+1]) m++,如果m大于25,那么就是无解,
否则的话 就是有m个位置所要+1,对于26个字符,只能往上加25次,那么根据隔板法,又由于 25次往上加这样的次数不一定要用光,所以再用一个盒子来装剩下的,25-m就是有m次往上加的位置已经确定了,不用管。
C(25-m+n+1-1,n+1-1)= C(25-m+n,n) 但是会爆ll,用java大数即可

import java.math.BigInteger;
import java.util.Scanner;

public class Main
{

    public static int N = 100010;
    public static int[] sa = new int[N];
    public static int[] ra = new int[N];

    public static void main(String[] args) 
    {
        Scanner cin = new Scanner(System.in 

);
        int t = cin.nextInt();
        while(t-- != 0)
        {
            int n = cin.nextInt();
            sa[0] = n+1;
            for(int i = 1; i <= n; ++i)
            {
                sa[i] = cin.nextInt();
                ra[sa[i]] = i;
            }
            if(n == 1)
            {
                System.out.println(26);
                continue;
            }
            int m = 0;
            for(int i = 1; i < n; ++i)
            {
                if(ra[sa[i]+1] > ra[sa[i+1]+1]) ++m;
            }
            if(m > 25)
            {
                System.out.println(0);
                continue;
            }
            int hh = 25-m;
            BigInteger h = BigInteger.valueOf(hh);
            BigInteger n1 = BigInteger.valueOf(n);
            BigInteger ans = BigInteger.ONE;
            for(BigInteger i = BigInteger.valueOf(n+1); i.compareTo(n1.add(h)) <= 0; i = i.add(BigInteger.ONE))
            {
                ans = ans.multiply(i);
            }
            for(BigInteger i = BigInteger.ONE; i.compareTo(h) <= 0; i = i.add(BigInteger.ONE))
            {
                ans = ans.divide(i);
            }
            System.out.println(ans);
        }

    }

}
展开阅读全文

没有更多推荐了,返回首页