我正在解决一个dp问题。问题是我有N个骰子;他们每个人都有K面,编号从1到K.现在我已经将N个骰子排成一行。如果我愿意,我可以旋转/翻转任何骰子。有多少种方法可以设置顶面,使所有顶面的总和等于S?
现在给我N,K,S;我必须计算总路数。值得一提的是我必须打印结果模100000007.我试图解决这个问题并为此编写代码,但我的代码不适用于这种情况:800 800 10000为什么?我无法理解。任何人都可以解释我的代码无效的原因。我的代码在这里:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<memory.h>
#define M 100000007
#define ull unsigned long long
using namespace std;
ull n,K,s,dp[1001][1001];
ull fnc(int num,int sum,int k)
{
ull temp;
if(num==0){
if(sum==0) return 1;
else return 0;
}
if(dp[num][k]!=-1)
return dp[num][k];
for(int i=1;i<=K;i++)
{
temp=temp%M+fnc(num-1,sum-i,i)%M;
}
return dp[num][k]=temp%M;
}
int main()
{
int T;
cin>>T;
for(int t=1;t<=T;t++)
{
cin>>n>>K>>s;
memset(dp,-1,sizeof(dp));
printf("Case %d: %lld\n",t,fnc(n,s,0));
}
return 0;
}
答案 0 :(得分:0)
您使用dp
的错误下标。
考虑有多少种方法可以获得800个骰子,每个骰子的数量从1到800, 如果在第一个骰子上将数字1设为最高,则得到总和10000 并且你在第二个骰子上最上面4个。
现在考虑如果你在第一个骰子上做2个最高点,有多少种方法可以得到10000 在第二个模具上最上面3个。
这两个数量是相同的:每个是获得798骰子(数字1到800)得到总和99995的方式的数量。那是你想要记忆的数量。
但是你甚至没有在dp
中分配足够的空间来存储这种部分答案。
我也不得不想知道你为什么使用unsigned long long
而不仅仅是unsigned long
,因为你的答案是模100000007。你应该永远不要
处理数字甚至接近signed long
的最大值。
答案 1 :(得分:0)
根据http://linux.die.net/man/3/memset:
memset()函数用常量字节c填充s指向的内存区域的前n个字节。
注意它没有说“常数无符号长long c”。
你在相同的范围内定义了值k和K,这是令人愤怒的。
你硬编码1001和-1而不是给它们正确的软编码变量名。
您的大多数变量名都是1个字符长。
您在return语句中有持久行为。
你绝对没有检查k,K和num的值是否在dp的适当范围内,这部分是硬编码1001的结果。
空格键是你的朋友,写作抄袭者,ha vet ad。。。。。。。。。