您的位置:首页 > 其它

51Nod-1043-幸运号码

2016-08-05 23:57 246 查看
ACM模版

描述



题解

动态规划,dp[i][j]表示i个数和为j的总数(这里包括开头为0的情况),则:

dp[i][j] = dp[i - 1][j - k](k:0 to 9)

最后,我们只需要用去掉0打头的情况*没有去掉0打头的情况累加并取模即可。

ans = (ans + dp[n & 1][i] * (dp[n & 1][i] - dp[(n - 1) & 1][i])) % mod;

这里去掉0的方法是
dp
[i]-dp[n-1][i]


另外注意一点是,这里使用了滚动数组优化内存。

代码

#include <iostream>
#include <cstring>

#define maxn 1005

using namespace std;

const int mod = 1e9 + 7;

long long dp[2][9 * maxn]; // 滚动数组

int n;

int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout);

int i, j, k;
long long ans;
cin >> n;

// 初始化
memset(dp, 0, sizeof(dp));
dp[0][1] = 1; // 两位和为1的只有一种
for (i = 0; i <= 9; ++i)
{
dp[1][i] = 1; // 1位和为i的只有一种
}

for (i = 2; i <= n; i++)
{
for (k = 0; k <= n * 9; k++) // dp[i][k]可以由dp[i-1][k-j]提供,j为0~9
{
long long sum = 0;
for (j = 0; j <= 9; j++)
{
if (k >= j)
{
sum = (sum + dp[(i - 1) & 1][k - j]) % mod;
}
else
{
break; // 无法通过减去一位j的状态提供
}
}
dp[i & 1][k] = sum; // 更新
}
}

ans = 0;
for (i = 0; i <= n * 9; i++)
{
ans = (ans + dp[n & 1][i] * (dp[n & 1][i] - dp[(n - 1) & 1][i])) % mod; // 把0去掉的方法就是dp [i]-dp[n-1][i]
}

cout << ans << endl;

return 0;
}


参考

《滚动数组》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp 滚动数组