zoukankan      html  css  js  c++  java
  • D. Count the Arrays 计数题

    D. Count the Arrays

    也是一个计数题。

    题目大意:

    要求构造一个满足题意的数列。

    • (n) 代表数列的长度
    • 数列元素的范围 ([1,m])
    • 数列必须有且仅有一对相同的数
    • 存在一个位置 (i),使得小于 (i) 这个位置的是严格递增的,大于这个位置则是严格递减的。

    这个题目也很容易把自己绕晕,所以我们要想开点。。。

    不要去太细节的考虑哪一个位置放什么之类的,而是考虑如何构造满足条件的序列。

    因为序列长度是 (n),范围是 (m),而且又必须有一对相同的数。

    所以即从 (m) 个数里,挑出 (n-1) 个不同的数,自然而然最大的那个数就是最高点。

    剩下的除了那两个相同的数之外都有两种选择,在这个最高点的左边或者右边。

    对于那两个相同的数只能在最高点的两侧,所以也就没有选择。

    然后有一对相同的数,所以此时有 (n-2) 种选择。

    所以总的方案数就是 :(C_{m}^{n-1}*2^{n-3}*(n-2))

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    const int mod=998244353;
    ll c[maxn],inv[maxn];
    void inv3(){
    	inv[1] = 1;
    	for (int i = 2; i < maxn; i++) {
    		inv[i] = (mod - mod / i)*inv[mod%i] % mod;
    	}
    }
    void init(int n){
    	c[0] = 1;
    	for (int i = 1; i <= n; i++) c[i] = c[i - 1] %mod * (n - i + 1) %mod * inv[i]%mod;
    }
    long long powmod(long long a, int b) {
    	long long ret = 1;
    	while (b) {
    		if (b & 1)ret = ret * a% mod;           //b&1 �������b%2 �ĺ���һ��
    		a = a * a % mod;
    		b >>= 1;
    	}
    	return ret;
    }
    int main(){
    	int n,m;
    	scanf("%d%d",&n,&m);
    	inv3(),init(m);
    	if(n==2) printf("0
    ");
    	else {
    		ll ans=c[n-1]*powmod(2,n-3)%mod*(n-2)%mod;
    		printf("%lld
    ",ans);
    	}
    	return 0;
    } 
    
  • 相关阅读:
    扑克牌顺子
    数组转 二叉树 ,并且输出二叉树的右视图
    数组中逆序对(归并排序思想)
    链表数字加和
    回文数字
    数组中 只出现一次的数
    判断是否有从根节点到叶子节点的节点值之和等于 sum
    双指针求 3个数和 为0的 数
    vue项目将css,js全部打包到html文件配置
    webpack4配置优化
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/12558201.html
Copyright © 2011-2022 走看看