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;
}
}