方案数,$dp$。
总的方案数有$n^m$种,符合要求的直接算不好算,可以算反面,即不符合要求的。
设$dp[i][j]$表示前$i$种等级填了$j$个位置,那么$dp[i][j]=sum(dp[i-1][j-k]*c[m-(j-k)][k])$。初始化$dp[0][0]=1$。
符合要求的方案数为$n^m-dp[n][m]$。数字会爆$long$ $long$,上$java$。
import java.math.BigInteger; import java.util.Scanner; public class Main { public static BigInteger GCD(BigInteger a,BigInteger b) { if(b.equals(BigInteger.ZERO)) return a; return GCD(b,a.mod(b)); } public static void main(String [] args) { Scanner cin = new Scanner(System.in); int M,N,L; BigInteger c[][] = new BigInteger[105][105]; BigInteger dp[][] = new BigInteger[105][105]; for(int i=0;i<=100;i++) c[i][0] = c[i][i] = BigInteger.ONE; for(int i=1;i<=100;i++) { for(int j=1;j<i;j++) { c[i][j]= c[i-1][j-1].add(c[i-1][j]); } for(int j=i+1;j<=100;j++) c[i][j] = BigInteger.ZERO; } while(cin.hasNext()) { M=cin.nextInt(); N=cin.nextInt(); L=cin.nextInt(); if(L>M) System.out.println("mukyu~"); else { BigInteger n = BigInteger.valueOf(N); BigInteger fm = n.pow(M); BigInteger fz = new BigInteger("0"); for(int i=0;i<=N;i++) { for(int j=0;j<=M;j++) { dp[i][j] = BigInteger.ZERO; } } dp[0][0] = BigInteger.ONE; for(int i=1;i<=N;i++) { for(int j=0;j<=M;j++) { for(int k=0;k<=L-1;k++) { if(j-k<0) continue; if(M-(j-k)<0) continue; dp[i][j] = dp[i][j].add(dp[i-1][j-k].multiply(c[M-(j-k)][k])); } } } fz=dp[N][M]; fz = fm.subtract(fz); BigInteger gcd = GCD(fz,fm); fz=fz.divide(gcd); fm=fm.divide(gcd); System.out.println(fz+"/"+fm); } } } }