Dollar Dayz POJ - 3181 (划分数(递推关系式优化)+大数(技巧))

本文探讨了如何使用动态规划解决物品划分问题,通过定义dp[i][j]为j的i划分总数,给出了详细的递推公式及代码实现,解决了划分方法数的计算问题。

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

传送门

划分数:有n个无区别的物品,将它们划分成不超过m组,求出划分方法数模M的余数。

这样的划分叫做n的m划分,特别的,m=n时称作n的划分数。DP不仅对于求解最优问题有效,对于各种排列组合的个数,概率或者期望之类的计算同样很有用。

定义:

dp[i][j]=j的i划分的总数

如果将j分划成i个的话,可以先取出k个,然后将剩余的j-k个分成i-1份,此时得到的递推式时这样的:

dp[i][j]=\sum dp[i-1][j-k]

但是这样递推是不正确的,会有很多重复,例如1+1+2和1+2+1就被当作不同的划分数来计数了。为了不重复计数,需要找到别的递推公式

当j>=i时,dp[i][j]=dp[i-1][j](j的i-1划分,相当于当前位取0的情况)+dp[i][j-i](当前位不取0,先把每一位置为1,再将剩下的j-i分下去)

j<i时,dp[i][j]=dp[i-1][j](当前位只能取0)

附上代码:

int n,m;
int dp[MAXM+1][MAXN+1];
void solve()
{
    dp[0][0]=1;
    for(int i=1;i<=m;i++){
        for(int j=0;j<=n;j++){
            if(j-i>=0){
                dp[i][j]=(dp[i-1][j]+dp[i][j-i])%mod;
            }else{
                dp[i][j]=dp[i-1][j];
            }
        }
    }
    printf("%d\n",dp[m][n]);
}

附上本题代码(使用两个long long数组进行拼接):


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long ll;

const int MAXN=1100;
const ll inf=1000000000000000000LL;

ll a[MAXN];
ll b[MAXN];

int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)!=EOF){
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        b[0]=1;
        for(int i=1;i<=k;i++){
            for(int j=i;j<=n;j++){
                a[j]=a[j]+a[j-i]+(b[j]+b[j-i])/inf;
                b[j]=(b[j]+b[j-i])%inf;
            }
        }
        if(a[n]==0){
            printf("%I64d\n",b[n]);
        }else{
            printf("%I64d%018I64d\n",a[n],b[n]);
        }
    }
    return 0;
}

 

### 连接方式与仿真细节 #### 1. **74LS194模块与LED显示器的连接** 74LS194作为一个双向通用移位寄存器,在本设计中用于记录硬币金额并驱动LED指示灯。其输出端Q0至Q3可以直接连接到四个独立的LED灯,分别表示不同的状态。例如: - 当74LS194处于`0001`状态时,仅第一个LED点亮,表示投入了一枚5角硬币; - 当74LS194处于`0010`状态时,第二个LED点亮,表示投入了一枚1元硬币。 这种简单的映射关系便于直观观察当前投币情况[^1]。为了实现这一功能,需要将74LS194的据输入端D0-D3设置为固定的高电平或低电平组合,并通过串行加载(SI)或者并行加载(LOAD)的方式写入据。 #### 2. **硬币传感器的接入** 硬币传感器通常会产生一个短暂的脉冲信号,该信号可以被用作74LS194的移位时钟CLK输入。具体来说: - 对于5角硬币,传感器产生的单个正向脉冲会被送入CLK端口; - 对于1元硬币,则需要连续两次相同的脉冲才能完全更新74LS194内部状态。 因此,可以在硬币识别单元之后加入分频电路或其他逻辑元件来调整不同面值硬币对应的脉宽差异。 #### 3. **仿真实现方法** 在EDA工具如Multisim、Proteus或ModelSim中进行系统级仿真前,应先单独测试各个子组件的行为特性。以下是几个关键步骤: ##### (a)**74LS194行为验证** 创建基本测试平台以检验74LS194能否正确响应各种模式切换命令以及据载入过程。确保所有预期的功能均能正常运作后再继续下一步集成工作。 ##### (b)**硬币传感模拟** 由于物理世界中的硬币感应装置难以直接移植到软件环境中再现,故建议采用虚拟开关代替实际设备生成人工触发事件序列供后续分析使用。这些开关应当具备精确的时间分辨率以便模仿真实的机械动作效果。 ##### (c)**整体联调** 最后一步便是把之前准备好的部件拼接到一起形成完整的闭环回路。在此阶段重点考察是否存在任何潜在冲突干扰因素影响最终表现质量。如果发现问题应及时定位原因并通过修改参配置加以修正直至满意为止。 ```python import time class CoinSensorSimulation: def __init__(self): self.coin_detected = False def detect(self, coin_type='half'): if coin_type == 'half': pulses = 1 elif coin_type == 'one': pulses = 2 else: raise ValueError("Invalid coin type.") for _ in range(pulses): self.coin_detected = True yield self.coin_detected time.sleep(0.1) # Simulated pulse duration. self.coin_detected = False yield self.coin_detected time.sleep(0.1) def simulate_74ls194_with_leds(): sensor_simulator = CoinSensorSimulation() led_states = { tuple([False]*3 + [True]): "Half Dollar", tuple([False]*2 + [True] + [False]): "One Dollar" } leds = [False] * 4 for detection_event in sensor_simulator.detect('one'): # Example usage with one dollar. if detection_event: # Shift operation simulation inside 74LS194 emulation. leds.pop(0) leds.append(True) else: leds[-1] = False current_state_tuple = tuple(leds) if current_state_tuple in led_states: print(f"{led_states[current_state_tuple]} detected.") simulate_74ls194_with_leds() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值