你推一下式子,你会发现,原问题等价于:
在长度为N的序列 对于一个位置编号(从左往右)NOW的位置,所能放的个数最多是NOW - 1,任意放,使得放的总和为K
可以构造一个母函数
1
∗
(
1
+
x
1
)
∗
(
1
+
x
2
+
x
2
2
)
.
.
.
.
.
.
.
1*(1+x1)*(1 + x2 + x2 ^2).......
1∗(1+x1)∗(1+x2+x22).......
但很难求出幂为k的项的系数之和。。。
考虑DP
F
(
i
,
j
)
前
i
项
,
幂
总
和
为
j
,
的
系
数
总
和
F(i,j)前i项,幂总和为j,的系数总和
F(i,j)前i项,幂总和为j,的系数总和
F
(
i
,
j
)
=
s
i
g
a
m
F
(
i
−
1
,
j
−
k
)
F(i,j) = sigam F(i - 1 , j - k)
F(i,j)=sigamF(i−1,j−k)
然后发现这个转移是
O
(
n
3
)
O(n^3)
O(n3)
考虑优化。。。
发现sigma那一块可以在上一次转移时候处理一个前缀和
然后就可以在平方级时间解决了,,,,,,
但是,我发现了事情的不对。。。。(51nod的题会这么水嘛??)
发现 如果用long long 会M飞 然而不用long long 前缀和就搞不了了。。。
于是乎要搞一下方程。。。。
然后这题就结束了。。。。
思维量有点大。。。
#include<bits/stdc++.h>
#define MAXN 1000
#define maxn 20000
using namespace std;
const int mod=1e9+7;
long long T , n , k;
int f[MAXN + 5][maxn + 5] , sum[maxn];
void init(){
f[0][0] = 1;
for(int i = 1 ; i <= MAXN ; i++){
for(int j = 0 ; j <= min(maxn , (i * (i - 1)) / 2) ; j++){
/*f[i][j] = sum[j];
if(j >= i)f[i][j] = (f[i][j] - sum[j - i] + mod) % mod;; */
f[i][j] = (f[i][j - 1] + f[i - 1][j]) % mod;
if(j >= i)f[i][j] = (f[i][j] - f[i - 1][j - i] + mod) % mod;
}
}
}
int main(){
init();
cin>>T;
while(T--){
cin>>n>>k;
cout<<f[n][k]<<endl;
}
}