fork download
  1. import java.math.BigInteger;
  2. import java.util.LinkedHashMap;
  3.  
  4. class CountStrings2 {
  5.  
  6. // cache. key: N:M
  7. private LinkedHashMap<String, BigInteger> sNM = new LinkedHashMap<String, BigInteger>();
  8. private final int P;
  9.  
  10. public CountStrings2(int P, int N, int M) {
  11. this.P = P;
  12. BigInteger S = computeS(N, M);
  13. System.out.println("P=" + P + " N=" + N + " M=" + M + " S=" + S);
  14. //outputCaches();
  15. computeAsympt(N,M);
  16. }
  17.  
  18. private BigInteger computeS(int N, int M) {
  19. String k = N + ":" + M;
  20. if (!sNM.containsKey(k)) {
  21. if (N < M) {
  22. b = BigInteger.valueOf(P).pow(N);
  23. } else {
  24. for (int i= 1; i < M; i++) {
  25. b = b.add(computeS(N-i, M));
  26. }
  27. b = b.multiply(BigInteger.valueOf(P-1));
  28. }
  29. sNM.put(k, b);
  30. }
  31.  
  32. return sNM.get(k);
  33. }
  34.  
  35. public void outputCaches() {
  36. System.out.println("============== SNM ==== (P=" + P + ")");
  37. for (String k : sNM.keySet()) {
  38. System.out.println("SNML " + k + "=" + sNM.get(k));
  39. }
  40. }
  41.  
  42. public void computeAsympt(int N, int M) { // asympotic approximation
  43. double theta = 1.0 / P;
  44. double probasympt = Math.pow(1 - Math.pow(theta, M - 1),N * (1 - theta));
  45. BigInteger S = computeS(N, M);
  46. BigInteger cc = BigInteger.valueOf(P).pow(N).multiply(BigInteger.valueOf(1000000)).divide(S);
  47. double probexact = 1000000.0/cc.doubleValue();
  48. System.out.printf("prob:%.4f asymptotic:%.4f\n" ,probexact, probasympt);
  49. }
  50.  
  51. public static void main(String[] args) {
  52. new CountStrings2(4, 50, 5);
  53.  
  54. }
  55. }
Success #stdin #stdout 0.04s 245632KB
stdin
Standard input is empty
stdout
P=4 N=50 M=5 S=1104822076420345943562167435148
prob:0.8716 asymptotic:0.8635