[Test1.11]-T3对合

Posted heanda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Test1.11]-T3对合相关的知识,希望对你有一定的参考价值。

Description:

一个排列 (A_n) 被称为是对合的,当且仅当:
?1 ≤ i ≤ n, (A_{Ai} = i)
Cob 想知道长度为 (n) 的排列中,有多少个具有对合的性质。但他不幸
发现,这是个水题。因此,他把问题加强了一下,抛给了你:
给定一个 (1)~(k) 的排列 (B_k) (k ≤ n),试求出:有多少个长度为 (n) 的对合
排列,满足 (B_k) 是其子序列。
由于答案可能很大,请对 1004535809 (479 × 221 + 1) 取模后输出。

Input:

第一行两个整数 (n), (k)
第二行 (k) 个整数,表示 (B_k)

Output:

一行一个整数,表示答案

数据范围:

1 ≤ k ≤ n ≤ 1e4

Solution:

首先找题目性质:
发现枚举(B_i)的前(m)个数在(1)~(k)匹配时
剩下(k-m)个数在k之外按顺序排好之后会一个找一个人回到原来的(1)~(k)匹配
那么前m个数需要按照顺序一个一个插入,所以方案是唯一的
那么后面的(k-m)个数可以通过组合数算方案数,剩下还有(n)-(k)个数可以发现就是没有任何限制的对合排列
直接递推预处理即可

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define R register
#define ll long long
using namespace std;
namespace IO
{
    template<class T>
    void rea(T &x)
    {
        char ch=getchar();int f(0);x = 0;
        while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
        while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        x = f?-x:x;
    }
    template<class T>
    T max(T a, T b) {return (a>b?a:b);}
    template<class T>
    T min(T a, T b) {return (a<b?a:b);}
}
using IO::rea;
#define mod 1004535809
long long n, k, b[10005], JieCheng[10005], inv[10005], ans, f[10005];
long long C(long long n, long long k){if(k > n) return 0;return JieCheng[n]*inv[k]%mod*inv[n-k]%mod;}
int kb[10005], is[10005];
bool vis[10005];
bool check(int m)
{
    memset(vis, 0, sizeof vis);
    for(R int i = 1; i <= m; ++i) kb[i] = b[i];
    sort(kb+1, kb+1+m);
    for(R int i = 1; i <= m; ++i) is[kb[i]] = i;
    for(R int i = 1; i <= m; ++i) if(!vis[kb[i]])
    {
        int FG = i, lunhuan = 0;
        vis[kb[i]] = 1;
        while(!vis[b[FG]]) vis[b[FG]] = 1, FG = is[b[FG]], lunhuan++;
        if(lunhuan >= 2) return 0;
    }
    return 1;
}
int main()
{
    freopen("permu.in","r",stdin);
    freopen("permu.out","w",stdout);
    using IO::max;using IO::min;
    rea(n), rea(k);
    for(R int i = 1; i <= k; ++i) rea(b[i]);
    JieCheng[1] = inv[1] = JieCheng[0] = inv[0] = 1;
    f[1] = f[0] = 1;
    for(R int i = 2; i <= max(n, k); ++i) JieCheng[i] = JieCheng[i-1]*i%mod;
    for(R int i = 2; i <= max(n, k); ++i) inv[i] = inv[mod%i]*(mod-mod/i)%mod;
    for(R int i = 2; i <= max(n, k); ++i) inv[i] = inv[i-1]*inv[i]%mod;
    for(R int i = 2; i <= max(n, k); ++i) f[i] = (f[i-1]+(i-1)*f[i-2])%mod;
    for(R int i = 0; i <= k; ++i)
    {
        long long X = 0, Y;
        if(check(i)) X = 1;
        Y = C(n-k, k-i);
        ans = (ans+X*Y*f[n-2*k+i])%mod;
    }
    printf("%lld
", ans);
    return 0;
}
/*input
10 5
5 1 4 3 2
output
26
*/

以上是关于[Test1.11]-T3对合的主要内容,如果未能解决你的问题,请参考以下文章

csp-s模拟测试101的T3代码+注释

20180516模拟赛T3——bag

uint64_t t3 = MAXDWORD + 1 == 0?

参数动作 其中T3可以是可选的

t3用户-角色-权限hibernate经典配置

T3 成绩单 题解