Sumsets(完全背包)

本文介绍如何通过完全背包算法解决Sumsets问题,给定一个整数N,计算使用只包含2的幂的整数之和表示N的所有可能方式的数量,并输出最后9位数作为结果。提供了一个高效的解决方案,包括母函数、完全背包、递推三种方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Sumsets
Time Limit: 2000MS Memory Limit: 200000K
Total Submissions: 15045 Accepted: 5997

Description

Farmer John commanded his cows to search for different sets of numbers that sum to a given number. The cows use only numbers that are an integer power of 2. Here are the possible sets of numbers that sum to 7: 
1) 1+1+1+1+1+1+1  2) 1+1+1+1+1+2  3) 1+1+1+2+2  4) 1+1+1+4  5) 1+2+2+2  6) 1+2+4 
Help FJ count all possible representations for a given integer N (1 <= N <= 1,000,000). 

Input

A single line with a single integer, N.

Output

The number of ways to represent N as the indicated sum. Due to the potential huge size of this number, print only last 9 digits (in base 10 representation).

Sample Input

7

Sample Output

6
题解:让用2^k的数相加组成n,刚看见就说是母函数,没打出来,打出来也肯定不对因为数据量太大肯定超时了;
其实可以用完全背包写;
思路很好想,把2^k的物品往背包里面放;dp[j]+=dp[j-i]为方案数;
递推也很好想,如果是奇数,直接dp[i]=dp[i-1]
如果是偶数,dp[i]可以由dp[i/2]得到;也可以由dp[i-1]得到;
完全背包:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define mem(x,y) memset(x,y,sizeof(x))
#define T_T while(T--)
#define SI(x) scanf("%d",&x)
#define SL(x) scanf("%lld",&x)
typedef long long LL;
const int MAXN=1000010;
const int MOD=1e9;
int bag[MAXN];
int main(){
	int N;
	 while(~scanf("%d",&N)){
	 	mem(bag,0);
	 	bag[0]=1;
	 	for(int i=1;i<=N;i*=2){
	 		for(int j=i;j<=N;j++){
	 			bag[j]+=bag[j-i];
	 			bag[j]%=MOD;
			 }
		 }
		 printf("%d\n",bag[N]);
	 }
	return 0;
}

  母函数超时:

#include<stdio.h>
const int MAXN= 1000010;
int main(){
    int a[MAXN],b[MAXN],N;
    while(~scanf("%d",&N)){
        int i,j,k;
        for(i=0;i<=N;i++){
            a[i]=1;b[i]=0;
        }
        for(i=2;i<=N;i*=2){
            for(j=0;j<=N;j++)
                for(k=0;k+j<=N;k+=i)
                    b[j+k]+=a[j];
                for(j=0;j<=N;j++)
                    a[j]=b[j],b[j]=0;
            }
        printf("%d\n",a[N]);
    }
    return 0;
}

  递推;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define mem(x,y) memset(x,y,sizeof(x))
#define T_T while(T--)
#define SI(x) scanf("%d",&x)
#define SL(x) scanf("%lld",&x)
typedef long long LL;
const int MAXN=1000010;
const int MOD=1e9;
int dp[MAXN];
int main(){
	int N;
	dp[0]=1;
	for(int i=1;i<MAXN;i++){
		if(i&1)dp[i]=dp[i-1];
		else dp[i]=(dp[i-1]+dp[i/2])%MOD;
	}
	while(~scanf("%d",&N))printf("%d\n",dp[N]);
	return 0;
}

  

转载于:https://www.cnblogs.com/handsomecui/p/5061234.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值