1310. ACM Diagnostics

http://acm.timus.ru/problem.aspx?space=1&num=1310

题目中说的 “the lexicographically increasing list”

10 和 2  谁更小呢,我刚开始没管这么多,直接按数的大小算的,把 2 放在了 10 的前面

然后也过了,但是题意是不是这个意思?

思路:

数位DP + 二分

代码:

import java.math.BigInteger;

import java.util.Scanner;



public class Main {



	/**

	 * @param args

	 */

	static final int N = 105;

	static final int M = 55;

	static final BigInteger[][][] dp=new BigInteger[N][M][M];

	public static void main(String[] args) {

		// TODO Auto-generated method stub

		Scanner in = new Scanner(System.in);

		for(int i=0;i<N;++i){

			for(int j=0;j<M;++j){

				for(int l=0;l<M;++l){

					dp[i][j][l]=BigInteger.ZERO;

				}

			}

		}

		int n,m,k;

		BigInteger b;

		n=in.nextInt();

		m=in.nextInt();

		k=in.nextInt();

		b=in.nextBigInteger();

		b=b.add(BigInteger.ONE);

		dp[0][1][0]=BigInteger.ONE;

		for(int i=0;i<n;++i){

			for(int l=0;l<k;++l){

				BigInteger tmp=BigInteger.ZERO;

				for(int j=1;j<=m;++j){

					tmp=tmp.add(dp[i][j][l]);

				}

				for(int w=1;w<=m;++w){

					dp[i+1][w][(l+w)%k]=dp[i+1][w][(l+w)%k].add(tmp);

				}

			}

		}

		BigInteger l=BigInteger.ZERO;

		BigInteger r =BigInteger.valueOf(m).pow(n).subtract(BigInteger.ONE);



		while(l.compareTo(r)<=0){

			BigInteger mid=l.add(r).divide(BigInteger.valueOf(2L));

			BigInteger tmp=gnum(mid,n,m,k);

			

			if(tmp.compareTo(b)>=0){

				r=mid.subtract(BigInteger.ONE);

			}

			else{

				l=mid.add(BigInteger.ONE);

			}

		}

		int[] a = new int[n];

		BigInteger M = BigInteger.valueOf((long)(m));

		for(int i=0;i<n;++i){

			a[i]=l.mod(M).intValue()+1;

			l=l.divide(M);

		}

		for(int i=n-1;i>=0;--i){

			System.out.print(a[i]);

			if(i>0)System.out.print(" ");

		}

		System.out.println();

		

	}

	public static BigInteger gnum(BigInteger mid,int n,int m,int mod){

		BigInteger M = BigInteger.valueOf((long)(m));

		int[] a = new int[n];

		for(int i=0;i<a.length;++i){

			a[i]=mid.mod(M).intValue()+1;

			mid=mid.divide(M);

		}

		BigInteger tmp=BigInteger.ZERO;

		int k=0;

		for(int i=n-1;i>=0;--i){

			for(int j=a[i]-1;j>=1;--j){

				tmp=tmp.add(dp[i+1][j][k]);

			}

			if(i==0){

				tmp=tmp.add(dp[i+1][a[i]][k]);

			}

			k=( (k-a[i])%mod+mod)%mod;

		}

		return tmp;

	}



}

 

你可能感兴趣的:(ACM)