题解 | 小红的好排列

小红的好排列

https://www.nowcoder.com/practice/67bf8c0b7fc64f3bb9cc21bf6dbbd14f

这是一道数学组合题,类似于高中排列组合那一章的一道题吧,只需要推出来式子

我们知道我们需要ned=n/2个

我们已经有cnt=n/3个满足条件

还需要rem=ned-cnt个

不满足条件的有n-cnt个

我们需要交换已经满足条件的(即3的倍数)与不满足条件的进行交换每次交换会使满足条件的个数+1

由此可知,我们需要从不满足条件的个数中挑选出rem个与满足条件的进行交换,得到式子C(rem,cnt)*C(rem,n-cnt)(我的组合数好像写反了,那就反着来吧)此时得到的数量已经满足条件了,此时这就是好数列,但是我们需要求出所有情况,通过观察发现,我们单独对此时不满足条件的进行排列不会影响满足条件的个数,所有我们在×上A(n-cnt,n-cnt)(对所有不满足条件的进行全排列),然后我们还需要对原先满足条件的cnt个进行全排列(内部进行全排列,也不会影响满足条件的个数,不然会缺少情况)综上所述,得到式子ans=c(rem,cnt)*c(rem,n-cnt)*fac[n-cnt]*fac[cnt](别忘记%mod)

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int INF = 0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
int fac[1000007];
int fastpow(int x,int p){
    int ans=1;
    while(p){
        if(p&1) ans=ans*x%mod;
        x=x*x%mod;
        p>>=1;
    }
    return ans;
}
int inv(int x){
    return fastpow(x,mod-2);
}
int c(int x,int y){
    return fac[y]*inv(fac[x])%mod*inv(fac[y-x])%mod;
}
void solve(){
    int n;cin>>n;
    int cnt=n/3;//已经有cnt个了
    int ned=n/2;//需要有need个
    int rem=ned-cnt;//还需要remain个
    int ans=c(rem,cnt)*c(rem,n-cnt)%mod*fac[n-cnt]%mod*fac[cnt]%mod;
    cout<<ans%mod;

}
signed main(){
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
    fac[0]=1;
    for(int i=1;i<=1000000;i++){
        fac[i]=fac[i-1]*i%mod;
    }
    int t=1;
    // cin>>t;
    while(t--){
        solve();
    }return 0;
}

全部评论
666
点赞 回复 分享
发布于 昨天 14:20 河南

相关推荐

2025-12-15 12:50
河北工程大学
sta666:我也是这个国际商业化的,三天,一天一面,就通过了,不过我是后端实习生,好好面感觉能过。
点赞 评论 收藏
分享
评论
4
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务