【硬币组合/动态规划/非典型题目】硬币组合方案数

硬币组合方案数
题目描述:
小Q非常富有,拥有非常多的硬币,小Q的拥有的硬币是有规律的,对于所有的非负整数K,小Q恰好> 各有两个数值为2^k,的硬币,所以小Q拥有的硬币是1,1,2,2,4,4……,小Q卖东西需要支付元钱,请问小Q想知道有多少种组合方案。 
输入:一个n (1<=n<=10^18),代表要付的钱 
输出:表示小Q可以拼凑的方案数目
 
只能解决小数据的:
复制代码
#include <iostream>
#include <math.h>
#include <bits/stdc++.h>
using namespace std;
#define MAXM 100000
#define MAXN 20
int dp[MAXM][MAXN];
int main() {
    int N;

    while (cin >> N) {
        memset(dp, 0, sizeof(dp));
        if (N == 0) {
            printf("1\n");
            continue;
        }
        int length = (int)(log10(N) / log10(2));
        for (int i = 0; i <= length; i++) {
            dp[0][i] = 1;
            dp[1][i] = 1;
        }
        dp[2][0] = 1;
        dp[1][0] = 1;
        for (int i = 1; i <= N; i++) {
            int k;
            for (int j = 1; j <= length; j++) {
                k = 1 << j;
                int res = 0;
                for (int m = 0; m < 3; m++) {
                    if (i - k * m >= 0) {
                        res += dp[i - k * m][j - 1];
                    }
                }
                dp[i][j] = res;
            }
        }
        printf("%d\n", dp[N][length]);
    }
    return 0;
}
复制代码

解决10^18数据的必须用到位运算

将硬币分为两份:1,2,4,8,16,.....和1,2,4,8,16....
组成两个数值为a,b的两个数字,他们的和是a+b=n; 
a在每一份中只可能有一种组合方式(二进制的思想)。
将a和b使用二进制表示,那么对于n=11,有a=101,b=110这种组合,即a=1+0+4=5,b=0+2+4=6。但是,请注意,对于a和b,在相同位取不同值,只有一种组合方法。
如111+100和101+110(即交换中间位)本质上都是同一种组合方法,因此对于该类型可以使用二进制异或进行去重。

 

复制代码
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
         Scanner scanner=new Scanner(System.in);
         int n=scanner.nextInt();
         if(n<=2) {
             System.out.println(n);
             return;
         }
         Set<Integer> countset=new HashSet<>();
         int stop=n/2;
         for(int i=1;i<=stop;i++) {
             int result=(i)^(n-i);//异或a和b
             countset.add(result);
         }
        System.out.println(countset.size());
    }
}
复制代码

测试样例

In:

8
10
11
1
0
9
10000

Out:

3
5
2
1
1
6
205

References

https://segmentfault.com/a/1190000011202631

posted @   stackupdown  阅读(605)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示