import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Main {
private final int nChars;
private int count = 0;
private Map<Task,BigInteger> memo = new HashMap<>();
public Main(int nChars) {
this.nChars = nChars;
}
/*+******************************************************************/
private static class Task {
public final int strlen;
public final int unpaired;
Task(int strlen, int unpaired) {
this.strlen = strlen;
this.unpaired = unpaired;
}
@Override
public int hashCode() {
return strlen*117 ^ unpaired;
}
@Override
public boolean equals
(Object other
) { if (!(other instanceof Task)) {
return false;
}
Task t2 = (Task)other;
return strlen==t2.strlen && unpaired==t2.unpaired;
}
@Override
return "("+strlen+","+unpaired+")";
}
}
/*+******************************************************************/
//System.out.println("getMemoed"+t);
if (t.strlen==0 || t.unpaired<0 || t.unpaired>t.strlen || t.unpaired>nChars
|| t.strlen%2 != t.unpaired%2) {
}
if (t.strlen==1) {
}
return memo.get(t);
}
/*+******************************************************************/
public int getCount() {
return count;
}
List<Task> stack = new ArrayList<Task>();
stack.add(t);
while (stack.size()>0) {
count += 1;
t = stack.remove(stack.size()-1);
//System.out.println("removed "+t);
result = getMemoed(t);
if (result!=null) {
continue;
}
Task t1 = new Task(t.strlen-1, t.unpaired+1);
Task t2 = new Task(t.strlen-1, t.unpaired-1);
if (r1==null) {
stack.add(t);
stack.add(t1);
if (r2==null) {
stack.add(t2);
}
continue;
}
if (r2==null) {
stack.add(t);
stack.add(t2);
continue;
}
result = compute(t1.unpaired, r1, nChars-t2.unpaired, r2);
memo.put(t, result);
//System.out.println(""+t1+":"+r1+", "+t2+":"+r2+" memo "+t+" = "+result);
}
return result;
}
return r1.add(r2);
}
public static void main
(String[] argv
) { argv
= new String[] {"500",
"4"}; int strlen
= Integer.
parseInt(argv
[0]); int nChars
= Integer.
parseInt(argv
[1]);
Main eps = new Main(nChars);
BigInteger result
= eps.
computeNDeep(new Task
(strlen,
0)); System.
out.
printf("%d: N(%d, %d, 0) = %d%n",
eps.getCount(), strlen, nChars,
result);
}
}
aW1wb3J0IGphdmEubWF0aC5CaWdJbnRlZ2VyOwppbXBvcnQgamF2YS51dGlsLkFycmF5TGlzdDsKaW1wb3J0IGphdmEudXRpbC5IYXNoTWFwOwppbXBvcnQgamF2YS51dGlsLkxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuTWFwOwoKcHVibGljIGNsYXNzIE1haW4gewogIHByaXZhdGUgZmluYWwgaW50IG5DaGFyczsKICBwcml2YXRlIGludCBjb3VudCA9IDA7CiAgcHJpdmF0ZSBNYXA8VGFzayxCaWdJbnRlZ2VyPiBtZW1vID0gbmV3IEhhc2hNYXA8PigpOwogIAogIHB1YmxpYyBNYWluKGludCBuQ2hhcnMpIHsKICAgIHRoaXMubkNoYXJzID0gbkNoYXJzOwogIH0KICAvKisqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovICAKICBwcml2YXRlIHN0YXRpYyBjbGFzcyBUYXNrIHsKICAgIHB1YmxpYyBmaW5hbCBpbnQgc3RybGVuOwogICAgcHVibGljIGZpbmFsIGludCB1bnBhaXJlZDsKCiAgICBUYXNrKGludCBzdHJsZW4sIGludCB1bnBhaXJlZCkgewogICAgICB0aGlzLnN0cmxlbiA9IHN0cmxlbjsKICAgICAgdGhpcy51bnBhaXJlZCA9IHVucGFpcmVkOwogICAgfQogICAgQE92ZXJyaWRlCiAgICBwdWJsaWMgaW50IGhhc2hDb2RlKCkgewogICAgICByZXR1cm4gc3RybGVuKjExNyBeIHVucGFpcmVkOwogICAgfQogICAgQE92ZXJyaWRlCiAgICBwdWJsaWMgYm9vbGVhbiBlcXVhbHMoT2JqZWN0IG90aGVyKSB7CiAgICAgIGlmICghKG90aGVyIGluc3RhbmNlb2YgVGFzaykpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgVGFzayB0MiA9IChUYXNrKW90aGVyOwogICAgICByZXR1cm4gc3RybGVuPT10Mi5zdHJsZW4gJiYgdW5wYWlyZWQ9PXQyLnVucGFpcmVkOwogICAgfQogICAgQE92ZXJyaWRlCiAgICBwdWJsaWMgU3RyaW5nIHRvU3RyaW5nKCkgewogICAgICByZXR1cm4gIigiK3N0cmxlbisiLCIrdW5wYWlyZWQrIikiOwogICAgfQogIH0KICAvKisqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovICAKICBwcml2YXRlIEJpZ0ludGVnZXIgZ2V0TWVtb2VkKFRhc2sgdCkgewogICAgLy9TeXN0ZW0ub3V0LnByaW50bG4oImdldE1lbW9lZCIrdCk7CiAgICBpZiAodC5zdHJsZW49PTAgfHwgdC51bnBhaXJlZDwwIHx8IHQudW5wYWlyZWQ+dC5zdHJsZW4gfHwgdC51bnBhaXJlZD5uQ2hhcnMKICAgICAgICB8fCB0LnN0cmxlbiUyICE9IHQudW5wYWlyZWQlMikgewogICAgICByZXR1cm4gQmlnSW50ZWdlci52YWx1ZU9mKDApOwogICAgfQogICAgCiAgICBpZiAodC5zdHJsZW49PTEpIHsKICAgICAgcmV0dXJuIEJpZ0ludGVnZXIudmFsdWVPZihuQ2hhcnMpOwogICAgfQogICAgcmV0dXJuIG1lbW8uZ2V0KHQpOwogIH0KICAvKisqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovICAKICBwdWJsaWMgaW50IGdldENvdW50KCkgewogICAgcmV0dXJuIGNvdW50OwogIH0KICBwdWJsaWMgQmlnSW50ZWdlciBjb21wdXRlTkRlZXAoVGFzayB0KSB7CiAgICBMaXN0PFRhc2s+IHN0YWNrID0gbmV3IEFycmF5TGlzdDxUYXNrPigpOwogICAgQmlnSW50ZWdlciByZXN1bHQgPSBudWxsOwogICAgc3RhY2suYWRkKHQpOwogICAgCiAgICB3aGlsZSAoc3RhY2suc2l6ZSgpPjApIHsKICAgICAgY291bnQgKz0gMTsKICAgICAgdCA9IHN0YWNrLnJlbW92ZShzdGFjay5zaXplKCktMSk7CiAgICAgIC8vU3lzdGVtLm91dC5wcmludGxuKCJyZW1vdmVkICIrdCk7CiAgICAgIHJlc3VsdCA9IGdldE1lbW9lZCh0KTsKICAgICAgaWYgKHJlc3VsdCE9bnVsbCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIAogICAgICBUYXNrIHQxID0gbmV3IFRhc2sodC5zdHJsZW4tMSwgdC51bnBhaXJlZCsxKTsKICAgICAgQmlnSW50ZWdlciByMSA9IGdldE1lbW9lZCh0MSk7CiAgICAgIFRhc2sgdDIgPSBuZXcgVGFzayh0LnN0cmxlbi0xLCB0LnVucGFpcmVkLTEpOwogICAgICBCaWdJbnRlZ2VyIHIyID0gZ2V0TWVtb2VkKHQyKTsKICAgICAgaWYgKHIxPT1udWxsKSB7CiAgICAgICAgc3RhY2suYWRkKHQpOwogICAgICAgIHN0YWNrLmFkZCh0MSk7CiAgICAgICAgaWYgKHIyPT1udWxsKSB7CiAgICAgICAgICBzdGFjay5hZGQodDIpOwogICAgICAgIH0KICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAocjI9PW51bGwpIHsKICAgICAgICBzdGFjay5hZGQodCk7CiAgICAgICAgc3RhY2suYWRkKHQyKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICByZXN1bHQgPSBjb21wdXRlKHQxLnVucGFpcmVkLCByMSwgbkNoYXJzLXQyLnVucGFpcmVkLCByMik7CiAgICAgIG1lbW8ucHV0KHQsICByZXN1bHQpOwogICAgICAvL1N5c3RlbS5vdXQucHJpbnRsbigiIit0MSsiOiIrcjErIiwgIit0MisiOiIrcjIrIiAgbWVtbyAiK3QrIiA9ICIrcmVzdWx0KTsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIHByaXZhdGUgQmlnSW50ZWdlciBjb21wdXRlKGludCB1MSwgQmlnSW50ZWdlciByMSwgaW50IHUyLCBCaWdJbnRlZ2VyIHIyKSB7CiAgICByMSA9IHIxLm11bHRpcGx5KEJpZ0ludGVnZXIudmFsdWVPZih1MSkpOwogICAgcjIgPSByMi5tdWx0aXBseShCaWdJbnRlZ2VyLnZhbHVlT2YodTIpKTsKICAgIHJldHVybiByMS5hZGQocjIpOwogIH0KICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmd2KSB7CiAgICBhcmd2ID0gbmV3IFN0cmluZ1tdIHsiNTAwIiwgIjQifTsKICAgIGludCBzdHJsZW4gPSBJbnRlZ2VyLnBhcnNlSW50KGFyZ3ZbMF0pOwogICAgaW50IG5DaGFycyA9IEludGVnZXIucGFyc2VJbnQoYXJndlsxXSk7CgogICAgTWFpbiBlcHMgPSBuZXcgTWFpbihuQ2hhcnMpOwogICAgCiAgICBCaWdJbnRlZ2VyIHJlc3VsdCA9IGVwcy5jb21wdXRlTkRlZXAobmV3IFRhc2soc3RybGVuLCAwKSk7CiAgICBTeXN0ZW0ub3V0LnByaW50ZigiJWQ6IE4oJWQsICVkLCAwKSA9ICVkJW4iLCAKICAgICAgICAgICAgICAgICAgICAgIGVwcy5nZXRDb3VudCgpLCBzdHJsZW4sIG5DaGFycywgCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQpOyAKICB9Cn0K