ZOJ3662:Math Magic(全然背包)

Yesterday, my teacher taught us about math: +, -, *, /, GCD, LCM... As you know, LCM (Least common multiple) of two positive numbers can be solved easily because of a * b = GCD (a, b)
* LCM (a, b).

In class, I raised a new idea: "how to calculate the LCM of K numbers". It‘s also an easy problem indeed, which only cost me 1 minute to solve it. I raised my hand and told teacher about
my outstanding algorithm. Teacher just smiled and smiled...

After class, my teacher gave me a new problem and he wanted me solve it in 1 minute, too. If we know three parameters N, M, K, and two equations:

1. SUM (A1, A2, ..., Ai, Ai+1,..., AK) = N

2. LCM (A1, A2, ..., Ai, Ai+1,..., AK) = M

Can you calculate how many kinds of solutions are there for Ai (Ai are all positive numbers). I began to roll cold sweat but teacher just smiled and smiled.

Can you solve this problem in 1 minute?

Input

There are multiple test cases.

Each test case contains three integers N, M, K. (1 ≤ N, M ≤ 1,000, 1 ≤ K ≤ 100)

Output

For each test case, output an integer indicating the number of solution modulo 1,000,000,007(1e9 + 7).

You can get more details in the sample and hint below.

Sample Input

4 2 2
3 2 2

Sample Output

1
2


题意:
给出n,m,k,问k个数的和为n。最小公倍数为m的情况有几种

思路:
由于最小公倍数为m,能够知道这些数必定是m的因子,那么我们仅仅须要选出这全部的因子,拿这些因子来背包就能够了
dp[i][j][k]表示放了i个数,和为j。公倍数为k的情况有几种
可是又问题。首先的问题内存,直接存明显爆内存。那么我们须要优化
1.由于我如今放第i个数,必定是依据放好的i-1个数来计算的。我们仅仅须要用滚动数组来解决就可以
2.对于公倍数,必定不能超过m,而我全部这些m的因子中的数字,不管选哪些,选多少,他们的最小公倍数依旧是这些因子之中的,那么我们能够进行离散化
解决好了之后就是全然背包的问题了


#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <math.h>
using namespace std;

const int mod = 1e9+7;

int dp[2][1005][105];
int a[1005],len,pos[1005];
int n,m,k;
int hash[1005][1005];

int gcd(int a,int b)
{
    return b==0?

a:gcd(b,a%b);
}
int lcm(int a,int b)
{
    return a/gcd(a,b)*b;
}

int main()
{
    int i,j,x,y;
    for(i = 1; i<=1000; i++)//预处理最小公倍数
    {
        for(j = 1; j<=1000; j++)
            hash[i][j] = lcm(i,j);
    }
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        len = 0;
        memset(pos,-1,sizeof(pos));
        for(i = 1; i<=m; i++)
        {
            if(m%i==0)
            {
                a[len] = i;
                pos[i] = len++;//离散化
            }
        }
        memset(dp[0],-1,sizeof(dp[0]));
        dp[0][0][0] = 1;
        for(i = 1; i<=k; i++)
        {
            memset(dp[i%2],-1,sizeof(dp[i%2]));
            for(j = i-1; j<=n; j++)//由于最小必定放1,而我前面已经放了i-1个数了。前面的和最少必定是i-1
            {
                for(x = 0; x<len; x++)//枚举前面数字的公倍数
                {
                    if(dp[(i+1)%2][j][x]==-1)
                        continue;
                    for(y = 0; y<len && (a[y]+j)<=n; y++)//枚举这一位放哪些数
                    {
                        int r = hash[a[y]][a[x]];
                        int s = j+a[y];
                        if(pos[r]!=-1 && r<=m)
                        {
                            r = pos[r];
                            if(dp[i%2][s][r] == -1) dp[i%2][s][r] = 0;
                            dp[i%2][s][r]+=dp[(i+1)%2][j][x];
                            dp[i%2][s][r]%=mod;
                        }
                    }
                }
            }
        }
        if(dp[k%2][n][pos[m]]==-1)
            printf("0\n");
        else
            printf("%d\n",dp[k%2][n][pos[m]]);
    }

    return 0;
}

时间: 2024-11-03 22:23:15

ZOJ3662:Math Magic(全然背包)的相关文章

ZOJ3662:Math Magic(完全背包)

Yesterday, my teacher taught us about math: +, -, *, /, GCD, LCM... As you know, LCM (Least common multiple) of two positive numbers can be solved easily because of a * b = GCD (a, b) * LCM (a, b). In class, I raised a new idea: "how to calculate the

Math Magic(完全背包)

Math Magic Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Description Yesterday, my teacher taught us about math: +, -, *, /, GCD, LCM... As you know, LCM (Least common multiple) of two positive numbers can b

hdu(1114)——Piggy-Bank(全然背包)

唔..近期在练基础dp 这道题挺简单的(haha).可是我仅仅想说这里得注意一个细节. 首先题意: 有T组例子,然后给出储蓄罐的起始重量E,结束重量F(也就是当它里面存满了零钱的时候).然后给你一个数N,代表如今有N种类型的硬币. 然后接下来N行,每行分别有两个数字P,W,P代表的是这样的类型零钱的价值,W则代表的是这样的类型零钱的重量,零钱的数量不限. 然后要你输出在满足当前重量就是F的情况下(也就是重量刚好为F),输出所需零钱价值最少的情况. 思路: 非常显然,这明显就是一个全然背包.可是这

nyist oj 311 全然背包 (动态规划经典题)

全然背包 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描写叙述 直接说题意,全然背包定义有N种物品和一个容量为V的背包.每种物品都有无限件可用.第i种物品的体积是c,价值是w. 求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大.本题要求是背包恰好装满背包时,求出最大价值总和是多少. 假设不能恰好装满背包,输出NO 输入 第一行: N 表示有多少组測试数据(N<7). 接下来每组測试数据的第一行有两个整数M.V. M表示物品种类的数目,V表示背

UVA 10306 e-Coins(全然背包: 二维限制条件)

option=com_onlinejudge&Itemid=8&page=show_problem&problem=1247">http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1247 题意: 对于每一个例子.先给定两个数n,m,分别表示有n种硬币,对于每一种硬币有两个价值.分别记做x,y,题目要求从中

HDU1248 寒冰王座 【数学题】or【全然背包】

寒冰王座 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10550    Accepted Submission(s): 5355 Problem Description 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,仅仅有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前. 死亡骑

HDU 1114 Piggy-Bank 全然背包

Piggy-Bank Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description Before ACM can do anything, a budget must be prepared and the necessary financial support obtained. The main income for this action come

UVALive 6073 Math Magic

                                              6073 Math MagicYesterday, my teacher taught us about math: +, -, *, /, GCD, LCM... As you know, LCM (Leastcommon multiple) of two positive numbers can be solved easily because of a ∗ b = GCD(a, b) ∗ LCM(a

POJ 3260 The Fewest Coins(多重背包+全然背包)

http://poj.org/problem?id=3260 题意: John要去买价值为m的商品. 如今的货币系统有n种货币,相应面值为val[1],val[2]-val[n]. 然后他身上每种货币有num[i]个. John必须付给售货员>=m的金钱, 然后售货员会用最少的货币数量找钱给John. 问你John的交易过程中, 他给售货员的货币数目+售货员找钱给他的货币数目 的和最小值是多少? 分析: 本题与POJ 1252类型: http://blog.csdn.net/u013480600