1155 Number of Dice Rolls With Target Sum

1 题目

You have d dice, and each die has f faces numbered 1, 2, ..., f.

Return the number of possible ways (out of fd total ways) modulo 10^9 + 7 to roll the dice so the sum of the face up numbers equals target.

Example 1:

Input: d = 1, f = 6, target = 3
Output: 1
Explanation: 
You throw one die with 6 faces.  There is only one way to get a sum of 3.

Example 2:

Input: d = 2, f = 6, target = 7
Output: 6
Explanation: 
You throw two dice, each with 6 faces.  There are 6 ways to get a sum of 7:
1+6, 2+5, 3+4, 4+3, 5+2, 6+1.

Example 3:

Input: d = 2, f = 5, target = 10
Output: 1
Explanation: 
You throw two dice, each with 5 faces.  There is only one way to get a sum of 10: 5+5.

Example 4:

Input: d = 1, f = 2, target = 3
Output: 0
Explanation: 
You throw one die with 2 faces.  There is no way to get a sum of 3.

Example 5:

Input: d = 30, f = 30, target = 500
Output: 222616187
Explanation: 
The answer must be returned modulo 10^9 + 7.

2 尝试解

2.1 分析

有d个骰子,每个骰子有f个面,分别有数字1,2...f。问如果要使得所有骰子的数字之和为target,有多少种解法。

典型的动态规划题目,N(f,d,target) = sum (N(d-1,f,target-i) for i in range(1,f+1))。终止条件为 d == 0或者target <= 0,此时如果d==target,则返回1,否则返回0。

2.2 代码

class Solution {
public:

    int numRollsToTarget(int d, int f, int target) {
        map<pair<int,int>,long> record;
        return help(d,f,target,record);
    }
    long help(int d,int&f,int target,map<pair<int,int>,long>&record){
        pair<int,int> index{d,target};
        if(record.count(index)!= 0) ;
        else if(target <= 0 || d == 0) 
            record[index] = (d==target?1:0);
        else{
            record[index] = 0;
            for(int i = 1; i <= f; i++){
                record[index] = (record[index] + help(d-1,f,target-i,record))%1000000007;
            }
        }
        return record[index];
    }
};

3 标准解

3.1 分析

如果两个正六面体骰子要掷出11,即5+6&6+5,如果骰子相对两面之和为固定值,即1和6相对,2和5相对,那么该问题等同于掷出2+1&1+2。即如果target > (f+1)*d/2, target = (f+1)*d-target

3.2 代码

class Solution {
public:

    int numRollsToTarget(int d, int f, int target) {
        map<pair<int,int>,long> record;
        return help(d,f,target,record);
    }
    long help(int d,int&f,int target,map<pair<int,int>,long>&record){
        target = min(target, d*(f+1)-target);
        pair<int,int> index{d,target};
        if(record.count(index)!= 0) ;
        else if(target <= 0 || d == 0) 
            record[index] = (d==target?1:0);
        else{
            record[index] = 0;
            for(int i = 1; i <= f; i++){
                record[index] = (record[index] + help(d-1,f,target-i,record))%1000000007;
            }
        }
        return record[index];
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值