*题解:P9035 「KDOI-04」Pont des souvenirs
解析
考虑钦定最大值 \(a_n\),这样更小的元素可以在 \([1,\min (a_n,k + 1 - a_n)]\) 下任意选。序列单调不减意味着差分序列中元素均为非负数。记 \(b\) 为 \(a\) 的差分序列,即 \(b_i = a_i - a_{i - 1}\),钦定最大值 \(a_n\),那么有 \(\sum_{i=1}^n b_i=a_n\)。
若 \(\min (a_n,k + 1 - a_n) = a_n\),则直接插板即可,方案数为 \(\binom{a_n - 1 + n - 1}{n - 1}\),\(a_n - 1\) 是因为 \(b_1 = a_1 > 0\),所以在最开始分一个给它。考虑 \([1,\lfloor \frac{k}{2}\rfloor]\) 的所有 \(a_n\),此时 \(\min\) 取到 \(a_n\),方案数为 \(\sum_{i = 1}^{\lfloor \frac{k}{2}\rfloor} \binom{i + n - 2}{n - 1}\)。
若 \(\min (a_n,k + 1 - a_n) = k + 1 - a_n\),则额外有限制 \(\sum_{i=1}^{n - 1} b_i \le k + 1 - a_n\),可以看作是只取 \([1,k + 1 - a_n]\) 这部分进行插板,方案数为 \(\binom{k + 1 - a_n - 1 + n - 1}{n - 1}\)。同理考虑 \([\lfloor \frac{k}{2}\rfloor + 1,k]\) 的所有 \(a_n\),方案数为 \(\sum_{i=\lfloor \frac{k}{2}\rfloor + 1}^{k} \binom{k - i + n - 1}{n - 1}\)。
两种情况都讨论完了,直接做是 \(O(Tk)\) 的,无法通过,考虑优化。
考虑上指标求和公式:
于是对于第一种情况,有:
对于第二种情况,有:
时间复杂度 \(O(n + k)\)。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2e7 + 10,mod = 1e9 + 7;
int fac[N],inv[N];
int C(int n,int m){
if(m > n) return 0;
return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod;
}
int qmi(int a,int b){
int res = 1;
while(b){
if(b & 1) res = 1ll * res * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
}
return res;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
// freopen("in.txt","r",stdin);
// freopen("out1.txt","w",stdout);
fac[0] = 1;
for(int i=1;i<N;i++){
fac[i] = 1ll * fac[i - 1] * i % mod;
}
inv[N - 1] = qmi(fac[N - 1],mod - 2);
for(int i=N - 2;i>=0;i--){
inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
}
int T;
cin>>T;
while(T--){
int n,k;
cin>>n>>k;
int res = (C(n + k / 2 - 1,n) + C(n + k - k / 2 - 1,n)) % mod;
cout<<res<<'\n';
}
return 0;
}
/*
*/

浙公网安备 33010602011771号