zoukankan      html  css  js  c++  java
  • AtCoder Beginner Contest 217G

    从小清新题目开始的康复之旅

    G - Groups

    Problem Statement

    You are given positive integers $N$ and $M$. For each $k=1,…,N$, solve the following problem.

    • Problem: We will divide $N$ people with ID numbers $1$ through $N$ into $k$ non-empty groups. Here, people whose ID numbers are equal modulo $M$ cannot belong to the same group.
      How many such ways are there to divide people into groups?
      Since the answer may be enormous, find it modulo $998244353$.

    Here, two ways to divide people into groups are considered different when there is a pair $(x,y)$ such that Person $x$ and Person $y$ belong to the same group in one way but not in the other.

    Constraints

    • $2≤N≤5000$
    • $2≤M≤N$
    • All values in input are integers.

    题目分析

    一个组合数学题

    一开始想简单了,以为是一个最简单的容斥,考虑最多分成n组的情况减去最多分成n-1组的情况,以为这个就是恰好n组的情况

    递推地看第n项的答案f(n),首先钦定某一个剩余类$a_1$的位置,其余的剩余类$a_j$随意插空有$Pi A(n, a_j)$种方案,然后减去恰好包含$n-1$项$f(n-1)*A(n-a_1,(n-1)-a_1)$,$n-2$项$f(n-2)*A(n-a_1,(n-2)-a_1)$...的方案。最后因为方案是无序的,再除以$(n-a_1)!$

    CE了一发emmm根本没想起来atcoder不能用万能头

    // #include<bits/stdc++.h>
    #include<cstdio>
    const int MO = 998244353;
    const int maxn = 5035;
    
    int n,m,a[maxn],f[maxn],fac[maxn],inv[maxn];
    
    int A(int n, int m)
    {
        return 1ll*fac[n]*inv[n-m]%MO;
    }
    int C(int n, int m)
    {
        return 1ll*fac[n]*inv[n-m]%MO*inv[m]%MO;
    }
    void Inc(int &x, int y)
    {
        x = (x+y+MO)%MO;
    }
    void Dec(int &x, int y)
    {
        x = (x-y+MO)%MO;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1; i<=n%m; i++) a[i] = n/m+1;
        for (int i=n%m+1; i<=m; i++) a[i] = n/m;
        inv[0] = inv[1] = fac[1] = 1;
        for (int i=2; i<=n; i++)
            inv[i] = 1ll*(MO-MO/i)*inv[MO%i]%MO;
        for (int i=2; i<=n; i++)
            inv[i] = 1ll*inv[i-1]*inv[i]%MO, fac[i] = 1ll*fac[i-1]*i%MO;
        for (int i=1; i<a[1]; i++) f[i] = 0;
        for (int i=a[1]; i<=n; i++)
        {
            int cnt = 1;
            for (int j=2; j<=m; j++)
                cnt = 1ll*cnt*A(i, a[j])%MO;
            Inc(f[i], cnt);
            for (int j=a[1]; j<i; j++)
                Dec(f[i], 1ll*f[j]*A(i-a[1], j-a[1])%MO);
            f[i] = 1ll*f[i]*inv[i-a[1]]%MO;
        }
        for (int i=1; i<=n; i++) printf("%d
    ",f[i]);
        return 0;
    }

    END

  • 相关阅读:
    result set sql server
    [转载]:C#、.Net面试题目及答案
    [转载]:合并两个已排序好的int数组,并排序返回c#实现
    [转载]实际举例C#引用类型和值类型的区别
    mysql 性能优化方案
    oracle 并行原理深入解析及案例精粹
    创建Oracle外部表 External Table
    Oracle 分区表
    MySQL索引类型一览
    MySQL配置文件mysql.ini参数详解、MySQL性能优化
  • 原文地址:https://www.cnblogs.com/antiquality/p/15270012.html
Copyright © 2011-2022 走看看