ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P7322 「PMOI-4」排列变换

2022-09-10 00:32:35  阅读:202  来源: 互联网

标签:const PMOI 变换 int P7322 ModInt x0 窗口 mod


P7322 「PMOI-4」排列变换

题目大意

给定常数 \(k\)。对于一个长度为 \(n\) 的排列 \(a\),定义

\[f(a)=\{\max_{1 \le i \le k} \{a_i\},\max_{2 \le i \le k+1} \{a_i\},\cdots,\max_{n-k+1 \le i \le n} \{a_i\}\} \]

对于一个长度为 \(n\) 的序列 \(a\),定义其权值 \(w(a)\) 为 \(a\) 中不同的数的个数。

现在,\(\text{ducati}\) 想知道,对于所有长度为 \(n\) 的排列 \(p\),它们的 \(w(f(p))\) 之和。

分析

就是给定一个长度为 kk 的滑动窗口在长度为 n 的排列上滑,问滑动窗口中的 max 变化了多少次。(滑动窗口不懂的可以理解成序列中连续 k个数。这里之所以不写不同数的个数而是变化次数,是因为题目求的是排列,而排列满足所有数各不相同,所以变化次数加 1 就等于不同 max 个数)

可以发现,因为枚举全排列中的每一个 i 都可以变成 n-i+1n! 个排列仍然完整),所以我们计算答案,求 minmax 其实是等价的。

因为向右滑动 1 长度的情况下,只有窗口最左的数会出窗口,而右边紧邻的那个数会进入窗口,所以我们实际上只需要对于每个窗口看最左边的数是否是窗口滑动之前的最小值,以及新加入的最右边的数是否是窗口滑动之后新的最小值即可。

对于最左边的数是窗口滑动之前是窗口最小值,进行一波推式子之后,可以发现它对答案的贡献有:

\[\sum_{i=1}^{n}C(n-i,k-1)(n-k)!(k-1)!(n-k) \]

其中从左往右,求和符合是枚举这个最小值的大小,组合数是令窗口中剩余的 k-1 个数大于最小值的值的个数,两个阶乘分别是窗口外面的数任意排列和窗口内部除去最小值外任意排列,最后一个 n-k 是计算排列中窗口可以在的位置有 n-k 个。(其实总窗口有 n-k+1 个,就是最左边那个无法移动了)

然后对于新进入的最右边的数是新的窗口最小值,式子是可以类比的:

\[\sum_{i=1}^{n}C(n-i,k)(n-k-1)!k!(n-k) \]

含义是类似的,只不过计算的是新加进去最右边那个数。

当然,只将这两部分加起来还有一些问题,实际上我们还会算重一部分,既满足最左边是窗口最小值,又满足新加入的是窗口的新最小值(且小于最左边的,或者你可以强制令最右边的是最小的,最左边的小于最右边的,实际上两种方法的式子是一样的),这部分答案需要减掉:

\[\sum_{i=1}^{n}C(n-i,k-1)(n-k-1)!(k-1)!(n-k)(i-1) \]

前面同样是类似的,最后的 i-1 是最右边小于最左边的个数,或者你也可以理解成是最左边小于最右边的个数。

注意最后还需要加上每个排列都缺少的 1 答案,也就是总答案加上 n!,因为我们最开始忽略了这部分。

Ac_code

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
using namespace std;

const int N = 5e5 + 10,mod = 998244353;

template<int T>
struct ModInt {
    const static int mod = T;
    int x;
    ModInt(int x = 0) : x(x % mod) {}
    int val() { return x; }
    ModInt operator + (const ModInt &a) const { int x0 = x + a.x; if (x0 >= mod) x0 -= mod; if (x0 < 0) x0 += mod; return ModInt(x0); }
    ModInt operator - (const ModInt &a) const { int x0 = x - a.x; if (x0 >= mod) x0 -= mod; if (x0 < 0) x0 += mod; return ModInt(x0); }
    ModInt operator * (const ModInt &a) const { return ModInt(1LL * x * a.x % mod); }
    ModInt operator / (const ModInt &a) const { return *this * a.inv(); }
    void operator += (const ModInt &a) { x += a.x; if (x >= mod) x -= mod; if (x < 0) x += mod;}
    void operator -= (const ModInt &a) { x -= a.x; if (x < 0) x += mod; if (x >= mod) x -= mod;}
    void operator *= (const ModInt &a) { x = 1LL * x * a.x % mod; }
    void operator /= (const ModInt &a) { *this = *this / a; }
    friend ostream &operator<<(ostream &os, const ModInt &a) { return os << a.x;}
    
    ModInt pow(int n) const {
        ModInt res(1), mul(x);
        while(n){
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    
    ModInt inv() const {
        int a = x, b = mod, u = 1, v = 0;
        while (b) {
            int t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        if (u < 0) u += mod;
        return u;
    }
    
};
typedef ModInt<mod> mint;

mint fact[N],infact[N];
int n,k;

void init()
{
    fact[0] = infact[0] = 1;
    for(int i=1;i<=n;i++) fact[i] = fact[i-1]*mint(i);
    infact[n] = fact[n].inv();
    for(int i=n-1;i;i--) infact[i] = infact[i+1]*mint(i+1);
}

mint C(int a,int b)
{
    return fact[a]*infact[b]*infact[a-b];
}

int main()
{
    ios;
    cin>>n>>k;
    init();
    mint ans = fact[n];
    for(int i=1;i<=n-k;i++)
    {
        ans += ((C(n-i,k-1)*fact[n-k])*fact[k-1])*mint(n-k);
        ans += ((C(n-i,k)*fact[n-k-1])*fact[k])*mint(n-k);
        ans -= (((C(n-i,k-1)*fact[n-k-1])*fact[k-1])*mint(n-k))*mint(i-1);
    }
    cout<<ans<<'\n';
    return 0;
}

标签:const,PMOI,变换,int,P7322,ModInt,x0,窗口,mod
来源: https://www.cnblogs.com/aitejiu/p/16675803.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有