• CodeForces 57C Array 组合计数+逆元


    题目链接:

    http://codeforces.com/problemset/problem/57/C

    题意:

    给你一个数n,表示有n个数的序列,每个数范围为[1,n],叫你求所有非降和非升序列的个数。

    题解:

    由于对称性,我们只要求非降序的个数就可以了(n个数全部相等的情况既属于非升也属于非降)

    我们在满足条件的n个数之前加一个虚节点1,在第n个数之后加一个虚节点n,那么考虑这n+2个数组成的非降序列:

    假设序列里的第i个数为a[i],我们设xi=a[i+1]-a[i]+1,1<=i<=n+1,则满足每个数>=1,且sum(x[1],x[2]...x[n+1])=2*n;

    那么相当于求将2*n分成n个部分,且每个部分的值大于等于1,则易得非降序列总数为:C(n,2*n-1)(2*n-1 选 n)

    所以最后的答案是2*C(n,2*n-1)-n;

    代码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 
     6 const int mod = 1000000007;
     7 typedef long long LL;
     8 int n;
     9 //扩展欧几里得
    10 void gcd(int a, int b, int &d, int &x, int &y) {
    11     if (!b) { d = a; x = 1; y = 0; }
    12     else { gcd(b, a%b, d, y, x); y -= x*(a / b); }
    13 }
    14 //求逆元
    15 int inv(int a) {
    16     int d, x, y;
    17     gcd(a, mod, d, x, y);
    18     return x;
    19 }
    20 //求阶乘
    21 int solve(int _n,int x) {
    22     LL ret = 1;
    23     while (_n--) {
    24         ret *= x;
    25         ret %= mod;
    26         x--;
    27     }
    28     return ret;
    29 }
    30 
    31 int main() {
    32     while (scanf("%d", &n) == 1 && n) {
    33         int ans = (LL)solve(n, 2 * n - 1)*inv(solve(n,n))%mod;
    34         ans = ans * 2 - n;
    35         ans = (ans%mod + mod) % mod;
    36         printf("%d
    ", ans);
    37     }
    38     return 0;
    39 }
  • 相关阅读:
    autodl3配置深度学习环境
    autodl使用2配置环境
    20220723图生成模型腾讯AI徐挺洋老师(分子生成)
    加班
    打比赛
    错过了一个比较大的编程比赛
    胡思乱想
    没有太复杂
    张远陆虎给从前的自己
    我还是会想
  • 原文地址:https://www.cnblogs.com/fenice/p/5460389.html
Copyright © 2020-2023  润新知