这个问题与模运算符%
有关。我们知道一般a % b
返回余数,当a除以b且余数大于或等于零且严格小于b时。但是当a和b的大小为10 ^ 9时,上述情况是否成立?
我似乎得到以下输入代码的负输出:
74 41 28
但是,更改最终输出语句会使工作和结果变得正确!
#include<iostream>
using namespace std;
#define m 1000000007
int main(){
int n,k,d;
cin>>n>>k>>d;
if(d>n)
cout<<0<<endl;
else
{
long long *dp1 = new long long[n+1], *dp2 = new long long[n+1];
//build dp1:
dp1[0] = 1;
dp1[1] = 1;
for(int r=2;r<=n;r++)
{
dp1[r] = (2 * dp1[r-1]) % m;
if(r>=k+1) dp1[r] -= dp1[r-k-1];
dp1[r] %= m;
}
//build dp2:
for(int r=0;r<d;r++) dp2[r] = 0;
dp2[d] = 1;
for(int r = d+1;r<=n;r++)
{
dp2[r] = ((2*dp2[r-1]) - dp2[r-d] + dp1[r-d]) % m;
if(r>=k+1) dp2[r] -= dp1[r-k-1];
dp2[r] %= m;
}
cout<<dp2[n]<<endl;
}
}
将最终输出语句更改为:
if(dp2[n]<0) cout<<dp2[n]+m<<endl;
else cout<<dp2[n]<<endl;
完成工作,但为什么需要它?
顺便说一句,代码实际上是我对this question
的解决方案答案 0 :(得分:1)
这是int
。
int
只能保存 -2,147,483,648 与 2,147,483,647 之间的值。
考虑将long long
用于你的m,n,k,d&amp; r变量。如果您的计算永远不会有负值,请尽可能使用unsigned long long
。
long long
可以将 -9,223,372,036,854,775,808 的值保存到 9,223,372,036,854,775,807
虽然unsigned long long
可以将值从 0 保存到 18,446,744,073,709,551,615 。 (2 ^ 64)
与无符号类型相比,有符号类型的正值范围大约减半,因为最高有效位用于符号;当您尝试分配大于指定数据类型强加的范围的正值时,将引发最高有效位并将其解释为负值。
答案 1 :(得分:1)
嗯,不,使用正数操作数的模数不会产生负面结果。
然而......
只有C标准才能保证int类型支持-32767到32767范围内的值,这意味着你的宏m不一定要扩展为int类型的文字。它会很长(但保证有足够大的范围)。
如果发生这种情况(例如,具有16位int类型和32位长类型的编译器),模数运算的结果将被计算为long,并且可能具有超过int可以表示的值。将该值转换为int(由于dp1是指向int的指针,因此dp1 [r]%= m等语句将需要)会给出未定义的行为。
答案 2 :(得分:0)
数学上,大数字并没有什么特别之处,但是计算机只有有限的宽度来记下数字,所以当事情变得太大时,你会得到溢出&#34;错误。一个常见的比喻是在汽车仪表板上行驶的里程计数器 - 最终它将显示为全9并且滚动到0。由于处理负数的方式,标准符号整数不会滚动到零,但是到一个非常大的负数。
你需要切换到更大的变量类型,以便它们快速溢出 - &#34; long int&#34;或者&#34; long long int&#34;而不只是&#34; int&#34;,范围与每个额外的宽度加倍。您还可以使用无符号类型进一步加倍,因为没有范围用于否定。