【算法题】逃离农场

牛牛在农场饲养了n只奶牛,依次编号为0到n-1, 牛牛的好朋友羊羊帮牛牛照看着农场.有一天羊羊看到农场中逃走了k只奶牛,但是他只会告诉牛牛逃走的k只奶牛的编号之和能被n整除。你现在需要帮牛牛计算有多少种不同的逃走的奶牛群。因为结果可能很大,输出结果对1,000,000,007取模。
例如n = 7 k = 4:
7只奶牛依次编号为0到6, 逃走了4只
编号和为7的有:{0, 1, 2, 4}
编号和为14的有:{0, 3, 5, 6}, {1, 2, 5, 6}, {1, 3, 4, 6},{2, 3, 4, 5}
4只牛的编号和不会大于18,所以输出5.

输入描述:
输入包括一行,两个整数n和k(1 ≤ n ≤ 1000),(1 ≤ k ≤ 50),以空格分割。

输出描述:
输出一个整数表示题设所求的种数。

输入例子:
7 4

输出例子:
5


分析:

考虑前 i 头奶牛、所有选取个数情况下的所有余数情况

(此题与另一道砌砖块的题神似:
http://blog.csdn.net/xiaxzhou/article/details/72782299)

  • 状态转移方程:

使用dp[i][j][t]表示前i头奶牛中选取j头的和除以 n 余为t的方案数

则方案分为两种:选取了第 i 头奶牛和没有选取第i头奶牛两个子问题

没有选择第 i 头奶牛的方案数:

dp[i1][j][t]

选择第 i 头奶牛的方案数:
dp[i1][j1][((t+n)i)

dp[i][j][t]=dp[i1][j][t]+dp[i1][j1][((t+n)i)%n]

可以被整除即:t==0
最终所求为dp[n][k][0]


#include <vector>
#include <iostream>
#include <string>

using namespace std;
//#define debug_

int func(int n, int k)
{
    vector<vector<int>> dp;
    vector<int> vec;
    vec.resize(n + 1);
    dp.resize(k + 1, vec);

    dp[0][0] = 1;

    for (auto i = 1; i < n + 1; ++i)//前i头奶牛
    {
        for (auto j = k; j > 0; --j)//选择j头奶牛
        {
            for (auto t = 0; t < n; ++t)//余t
            {
                dp[j][t] = (dp[j][t] + dp[j - 1][((t + n) - i) % n]) % 1000000007;
            }
        }
    }

    return dp[k][0];
}

int main()
{
    int n, k;
#ifdef debug_
    n = 7;
    k = 4;
#else
    cin >> n;
    cin >> k;
#endif

    cout << func(n, k);

    return 0;
}

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值