码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces1312D Count the Arrays 组合数学

时间:2020-03-10 11:57:17      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:auto   static   splay   pen   open   mem   inline   epo   sync   

题意

给你\(n\)\(m\),问满足以下条件的数列的个数:

  • 数列长度为\(n\)
  • 数列值域范围为\(\left[1,m\right]\)
  • 数列有且仅有一对相等的数
  • 数列是单峰数列(先严格递增后严格递减,严格递增或严格递减)

解题思路

首先从\(m\)元素中挑出\(n-1\)个不同的值,有\(C_m^{n-1}\)种方法。现在数列的值域就可以只看成\(\left[1,n-1\right]\)了。

然后这\(n-1\)个元素中,先放置好\(n-1\),假设重复元素的值为\(i(i\in\left[1,n-2\right])\)。那么这3个元素的位置只有一种放置方法符合条件。还剩下\(n-3\)个元素,这些元素既可以在峰的左侧,也可以在峰的右侧,且对于所有分法都有且只有一种放置方法,所以有\(2^{n-3}\)种方法。最后乘上\(i\)的取值方法数也就是\(n-2\),结果如下:
\[ Ans=(n-2)C_m^{n-1}2^{n-3} \]

AC代码

#include <bits/stdc++.h>
using namespace std;
  
typedef long long ll;
typedef pair<int,int> pi;
 
#define x first
#define y second
  
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define endl '\n'
  
const double PI=acos(-1.0);
 
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int l,int r){return l+rng()%(r-l+1);}
  
namespace IO{
    bool REOF = 1; //为0表示文件结尾
    inline char nc() {
        static char buf[100000], *p1 = buf, *p2 = buf;
        return p1 == p2 && REOF && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? (REOF = 0, EOF) : *p1++;
    }
  
    template<class T>
    inline bool read(T &x) {
        char c = nc();bool f = 0; x = 0;
        while (c<'0' || c>'9')c == '-' && (f = 1), c = nc();
        while (c >= '0'&&c <= '9')x = (x << 3) + (x << 1) + (c ^ 48), c = nc();
        if(f)x=-x;
        return REOF;
    }
  
    template<typename T, typename... T2>
    inline bool read(T &x, T2 &... rest) {
        read(x);
        return read(rest...);
    }
  
  
    inline bool need(char &c) { return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')); }
    // inline bool need(char &c) { return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || c==' '; }
  
    inline bool read_str(char *a) {
        while ((*a = nc()) && need(*a) && REOF)++a; *a = '\0';
        return REOF;
    }
  
    inline bool read_dbl(double &x){
        bool f = 0; char ch = nc(); x = 0;
        while(ch<'0'||ch>'9')  {f|=(ch=='-');ch=nc();}
        while(ch>='0'&&ch<='9'){x=x*10.0+(ch^48);ch=nc();}
        if(ch == '.') {
            double tmp = 1; ch = nc();
            while(ch>='0'&&ch<='9'){tmp=tmp/10.0;x=x+tmp*(ch^48);ch=nc();}
        }
        if(f)x=-x;
        return REOF;
    }
  
    template<class TH> void _dbg(const char *sdbg, TH h){ cerr<<sdbg<<'='<<h<<endl; }
  
    template<class TH, class... TA> void _dbg(const char *sdbg, TH h, TA... a) {
        while(*sdbg!=',')cerr<<*sdbg++;
        cerr<<'='<<h<<','<<' '; _dbg(sdbg+1, a...);
    }
     
    template<class T> ostream &operator<<(ostream& os, vector<T> V) {
        os << "["; for (auto vv : V) os << vv << ","; return os << "]";
    }
  
    template<class T> ostream &operator<<(ostream& os, set<T> V) {
        os << "["; for (auto vv : V) os << vv << ","; return os << "]";
    }

    template<class T> ostream &operator<<(ostream& os, map<T,T> V) {
        os << "["; for (auto vv : V) os << vv << ","; return os << "]";
    }
 
    template<class L, class R> ostream &operator<<(ostream &os, pair<L,R> P) {
        return os << "(" << P.st << "," << P.nd << ")";
    }
     
    #define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
}
  
using namespace IO;
const int maxn=2e5+5;
const int maxv=2e5+5;
const int mod=998244353; // 998244353 1e9+7
const int INF=1e9+7; // 1e9+7 0x3f3f3f3f 0x3f3f3f3f3f3f3f3f
const double eps=1e-12;
  
int dx[4]={0,1,0,-1};
//int dx[8]={1,0,-1,1,-1,1,0,-1};
int dy[4]={1,0,-1,0};
//int dy[8]={1,1,1,0,0,-1,-1,-1};
 
// #define ls (x<<1)
// #define rs (x<<1|1)
// #define mid ((l+r)>>1)
// #define lson ls,l,mid
// #define rson rs,mid+1,r

// int tot,head[maxn];
// struct Edge{
//  int v,nxt;
//     Edge(){}
//     Edge(int _v,int _nxt):v(_v),nxt(_nxt){}
// }e[maxn<<1];
// void init(){
//  tot=1;
//  memset(head,0,sizeof(head));
// }
// void addedge(int u,int v){
//  e[tot]=Edge(v,head[u]); head[u]=tot++;
//  e[tot]=Edge(u,head[v]); head[v]=tot++;
// }
// void addarc(int u,int v){
//     e[tot]=Edge(v,head[u]); head[u]=tot++;
// }
  
/**
 * **********     Backlight     **********
 * 仔细读题
 * 注意边界条件
 * 记得注释输入流重定向
 * 没有思路就试试逆向思维
 * 加油,奥利给
 */
ll n,m;
ll qp(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}

ll inv(ll x){return qp(x,mod-2);}

void solve(){
    read(n,m);
    ll ans=n-2;
    for(int i=1;i<=m;i++)ans=ans*i%mod;
    for(int i=1;i<=n-1;i++)ans=ans*inv(i)%mod;
    for(int i=1;i<=m-n+1;i++)ans=ans*inv(i)%mod;
    ans=ans*qp(2,n-2)%mod;
    ans=ans*inv(2)%mod;
    printf("%lld\n",ans);
}
 
int main()
{
    // freopen("in.txt","r",stdin);
    // ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    // int _T; read(_T); for(int _=1;_<=_T;_++)solve();
    // while(read(n))solve();
    solve();
    return 0;
}

Codeforces1312D Count the Arrays 组合数学

标签:auto   static   splay   pen   open   mem   inline   epo   sync   

原文地址:https://www.cnblogs.com/zengzk/p/12454536.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!