牛客2024年七夕节比赛:牛郎织女来相会(组合数的考虑方向)

题目描述

七夕已经到了!牛郎织女迫切想要见面,但我们都知道他们要想跨越银河就需要构造鹊桥。

现在,天上飞了无数只喜鹊并且飞行高度 h (1≤h≤m )h\ (1 \leq h \leq m\ )h (1≤h≤m ),他们都想尽快帮助牛郎织女见面。

鹊桥的形状是一个倒 VVV,倒 VVV 指的是 存在 x∈(1,n)x \in (1,n)x∈(1,n) 使得 ai−1<ai ( i∈(1,x] )a_{i-1} <a_i\ (\ i \in (1,x]\ )ai−1​<ai​ ( i∈(1,x] ) 且 ai>ai+1 ( i∈[x,n) )a_i>a_{i+1}\ (\ i \in [x, n)\ )ai​>ai+1​ ( i∈[x,n) ) 。 

即对于最大值所在的位置,在这个位置左边的所有数字严格递减,在这个位置右边的所有数字严格递减。

但若想鹊桥稳固则必须有且仅有两个位置的喜鹊飞行高度一样。

牛郎织女想请你帮忙计算一下有多少种稳固的鹊桥,以便于他们见面没有安全隐患。

例:1 3 6 9 7 6 4 21\ 3\ 6\ 9\ 7\ 6\ 4\ 21 3 6 9 7 6 4 2 即为一个稳固的鹊桥。

答案可能很大,请你输出答案对 109+710^9+7109+7 取模后的结果。

输入描述:

输入一行两个正整数 n,m ( 3≤n≤m≤106 )n,m\ (\ 3 \leq n \leq m \leq  10^6\ )n,m ( 3≤n≤m≤106 )

输出描述:

输出一行一个结果,由于答案过大请对 109+710^9+7109+7 取模。

示例1

输入

复制3 4

3 4

输出

复制6

6

说明

对于样例 共有如下 666 种稳固的鹊桥
1 4 11\ 4\ 11 4 1
1 3 11\ 3\ 11 3 1
1 2 11\ 2\ 11 2 1
2 3 22\ 3\ 22 3 2
2 4 22\ 4\ 22 4 2
3 4 33\ 4\ 33 4 3

做法

我们先从m个高度中选n-1个不同的高度(有两个数要求相同,所以选n-1个不同的数即可),就是组合数C[m][n-1]。然后最大的那个数做桥的顶端,不用管。剩下的n-2个数都可以拿来做那两个相同的数,因此再乘以(n-2)。剩下的n-3个数,每个数都能放在桥的左右两侧,因此再乘以2的n-3次方

#include<bits/stdc++.h>
using namespace std;

int n,m;
long long jc[1000010],ny[1000010];
const long long mod=1e9+7;

long long ksm(long long a,long long b){
    long long ans=1;
    while(b){
        if(b%2) ans=ans*a%mod;
        b/=2;
        a=a*a%mod;
    }
    return ans;
}

int main(){
    
    jc[0]=1;
    for(int i=1;i<=1000000;i++) jc[i]=1ll*jc[i-1]*i%mod;

    ny[1000000]=ksm(jc[1000000],mod-2);
    for(int i=1000000-1;i>=0;i--) ny[i]=ny[i+1]*1ll*(i+1)%mod;
    
    scanf("%d%d",&n,&m);

    if(n>m){//不足以搭成桥
        cout<<0;
        return 0;
    }
    
    cout<<1ll*jc[m]*ny[n-1]%mod*ny[m-n+1]%mod*n-2%mod*ksm(2,n-3)%mod;
    
}

我当时写的时候没想到,一直在想,桥的每个位置(共有n个位置)有多少个不同的数能放。其实换个方向考虑就行,n-1个数能放哪些位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值