import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class Main { private static Map<Long, Long> mem; public static void main(String[] args){ Scanner in = new Scanner(System.in); while(in.hasNext()){ solution(in); } } /** * 数学法 * * f(n)表示凑成n元的方案数 * 方案数即是不同的解向量[x1,x2,x3,x4,...]的个数 * * 1. n为奇数(1种情况) * 必需使用一个1元钱 * n = 1+2*x1+2*x2+4*x3+4*x4+... * f(n)=f(n−1)=f((n−1)/2)=f(n/2)=f(n>>1) (n为奇数) * * 2. n为偶数(2种情况) * (1) 不使用两个1元钱 * n = 2*x1+2*x2+4*x3+4*x4+... * f(n)=f(n/2)=f(n>>1) * * (2) 同时使用两个1元钱 * n = 1+1+2*x1+2*x2+4*x3+4*x4+... * f(n)=f(n-2)=f((n−2)/2)=f(n/2-1)=f((n>>1)-1) * * f(n)=f(n>>1)+f((n>>1)-1) (n为偶数) * * 综上可知: * * { f(n>>1) , (n为奇数) * f(n) = { * { f(n>>1)+f((n>>1)-1), (n为偶数) * * @param in */ private static void solution(Scanner in){ long n = in.nextLong(); mem = new HashMap<>(); mem.put(1L, 1L); mem.put(2L, 2L); long result = dp(n); System.out.println(result); } /** * 动态规划 * * dp(i)表示凑成i元的方案数 * * { dp(i>>1) , (n为奇数) * dp(i) = { * { dp(i>>1)+dp((i>>1)-1), (n为偶数) * * @param num * @return */ private static long dp(long num){ if(mem.containsKey(num)){ return mem.get(num); } long count; if(isOdd(num)){ count = dp(num>>1); }else{ count = dp(num>>1) + dp((num>>1)-1); } mem.put(num, count); return count; } /** * 是否奇数 * @param num * @return */ private static boolean isOdd(long num){ return ((num&1) == 1); } /** * 是否偶数 * @param num * @return */ private static boolean isEven(long num){ return ((num&1) == 0); } }