0
点赞
收藏
分享

微信扫一扫

BZOJ4402 Claris的剑 [组合数学]

boomwu 2022-07-12 阅读 57

​​BZOJ4402 Claris的剑​​​ 注意到
" 我们认为两把剑本质不同,当且仅当存在至少一个宽度,在两把剑的宽度序列里面出现次数不一样 "
冷静分析后发现,我们可以根据字典序最小来构造序列
或者从另一方面想:将某些剑重新排列后,跟以下两种本质相同
1.BZOJ4402 Claris的剑 [组合数学]_i++
2.BZOJ4402 Claris的剑 [组合数学]_#include_02
考虑枚举最后的 m,也就是钦定序列的最大值,然后将二元组插入序列,是一个经典的插板问题
如果最后的长度为 n,最大值为 m,那么方案数为 BZOJ4402 Claris的剑 [组合数学]_i++_03
于是有 BZOJ4402 Claris的剑 [组合数学]_i++_04 的做法,就是枚举最后的最大值与长度
考虑直接枚举 BZOJ4402 Claris的剑 [组合数学]_#include_05
BZOJ4402 Claris的剑 [组合数学]_#include_06
BZOJ4402 Claris的剑 [组合数学]_#include_07
于是就可以 BZOJ4402 Claris的剑 [组合数学]_#include_08

#include<bits/stdc++.h>
#define N 2000050
using namespace std;
const int Mod = 1e9 + 7;
typedef long long ll;
ll add(ll a, ll b){ return (a + b) % Mod;}
ll mul(ll a, ll b){ return (a * b) % Mod;}
int n, m;
ll fac[N], inv[N];
ll calc(int x, int y){
x >>= 1; --y; return mul(fac[x + y], mul(inv[x], inv[y]));
}
int main(){
scanf("%d%d", &n, &m);
ll ans = n && m; m = min(n, m);
fac[0] = fac[1] = inv[0] = inv[1] = 1;
for(int i = 2; i <= n; i++) fac[i] = mul(fac[i-1], i), inv[i] = mul(Mod-Mod/i, inv[Mod%i]);
for(int i = 2; i <= n; i++) inv[i] = mul(inv[i], inv[i-1]);
for(int i = 2; i <= m; i++)
ans = add(ans, add(calc(n-i, i), calc(n-i-1, i)));
cout << ans; return 0;
}


举报

相关推荐

0 条评论