【发布时间】:2017-08-05 07:45:44
【问题描述】:
给定两个整数 n 和 k,我想计算有多少个不同的数组由从 1 到 n 的数字组成,这样正好有 k 个逆对。 (即配对 i,j 使得 i<j 和 a[i]>a[j])Mod 10^9+7。
我正在使用动态编程,我将 DP[i][j] 定义为具有 i 个元素且恰好有 j 个反转的数组的数量,然后我得出了递归:
DP[i][j]=DP[i-1][j]+dp[i-1][j-1]+...+dp[i-1][j-i+1]
另外,我注意到:
DP[i][j-1]=DP[i-1][j-1]+DP[i-1][j-2]+...+DP[i-1][j-i]
因此,结合两个总和,我们得到:
DP[i][j]=DP[i-1][j]+DP[i][j-1]-DP[i-1][j-i]
我编写了以下动态编程解决方案,它适用于大 n 直到 n,k 大约 800。但是,一旦我传递了这些值(例如,n=1000,k=990),结果就会溢出,我不是确定为什么会这样。这是我的解决方案:
class Solution {
public:
long long MOD = 1e9+7;
int kInversePairs(int n, int k) {
vector< vector<long long> > dp(1001, vector<long long>(1001, -1));
return solve(dp, n, k);
}
long long solve(vector< vector<long long> >& dp, int n, int k){
if (k<0)return 0;
if (k==0)return 1;
if (n==0)return 0;
if (dp[n][k]!=-1)return dp[n][k];
dp[n][k]=solve(dp, n-1, k)%MOD;
dp[n][k]+=solve(dp, n, k-1)%MOD;
dp[n][k]-=solve(dp, n-1, k-n)%MOD;
//if (dp[n][k]<0){
// cout << "Overflow: " << solve(dp, n-1, k-n) << " " << solve(dp, n-1, k) << " " << solve(dp, n, k-1) << endl;
//}
return dp[n][k]%=MOD;
}
};
【问题讨论】:
-
投反对票的人能否解释他投反对票的原因?我显然已经尝试了很多,我的问题很清楚,而且我没有要求任何人解决我的作业(这不是)。看来我这些天在堆栈溢出上发布的任何问题都毫无理由地被否决了!
-
int kInversePairs,long long solve-- 看到这个问题了吗?当您从kInversePairs返回solve的结果时,您的编译器应该会警告您。 -
@PaulMcKenzie 不,将其更改为 long long 仍然会溢出。所有答案都采用 mod 1e9+7 表示,它可以在 int 上表示,所以这仍然不是问题,但即使将 int 更改为 long long 也不会改变溢出。
标签: c++ algorithm dynamic-programming integer-overflow