zoukankan      html  css  js  c++  java
  • AGC002F Leftmost Ball

    题目传送门

    Description

    (n)种颜色的球,每种(k)个,((n,kleq 2000))(ncdot k)个球排成一排,把每种颜色最左边的那个涂成白色(初始不含白色),求不同序列个数。

    Solution

    考虑一种性质,该序列的前缀中白球个数应大于其他颜色的种类。

    考虑(O(n^2))的做法,设(f_{i,j})为已经放了(i)个白球,放完了(j)中其它颜色的方案数。

    (i)位若为白球,(f_{i,j}+=f_{i-1,j}),即放直接放一个白球

    (i​)为若为其它颜色的球,(f_{i,j}+=f_{i,j-1}cdot (n-j+1)cdot C_{ncdot k-i-(j-1)cdot (k-1)-1}^{k-2}​),即在第一个空位选一个颜色放,然后在后面剩下的位置放该颜色剩下(k-2​)个球。

    综上所述:

    [f_{i,j}=f_{i-1,j}+f_{i,j-1}cdot (n-j+1)cdot C_{ncdot k-i-(j-1)cdot (k-1)-1}^{k-2} ]

    [f_{i,0}=1,Ans=f_{n,n} ]

    Code

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=2005, P=1000000007;
    int f[N][N], fac[N*N], ifac[N*N];
    
    int C(int n, int m){return fac[n]*ifac[m]%P*ifac[n-m]%P;}
    int Pow(int x, int t)
    {
        int res=1;
        while (t) {if (t&1) res=res*x%P; x=x*x%P; t>>=1;}
        return res;
    }
    
    signed main()
    {
        int n, k; scanf("%d%d", &n, &k);
        if (k==1) {puts("1"); return 0;}
        f[0][0]=fac[0]=1; 
        for (int i=1; i<=4e6; i++) fac[i]=fac[i-1]*i%P; 
        ifac[(int)4e6]=Pow(fac[(int)4e6], P-2);
        for (int i=4e6-1; ~i; i--) ifac[i]=ifac[i+1]*(i+1)%P;
        for (int i=1; i<=n; i++)
            for (int j=0; j<=i; j++)
                f[i][j]=f[i-1][j]+(j!=0)*
                    (f[i][j-1]*(n-j+1)%P*C(n*k-i-(j-1)*(k-1)-1, k-2)%P)%P;
        printf("%d
    ", f[n][n]);
        return 0;
    }
    
    
  • 相关阅读:
    树链剖分 (模板) 洛谷3384
    ST表 (模板) 洛谷3865
    IOI 2005 River (洛谷 3354)
    IOI 2005 River (洛谷 3354)
    poj1094 Sorting It All Out
    poj1094 Sorting It All Out
    spfa(模板)
    HAOI 2006 受欢迎的牛 (洛谷2341)
    HAOI 2006 受欢迎的牛 (洛谷2341)
    洛谷1850(NOIp2016) 换教室——期望dp
  • 原文地址:https://www.cnblogs.com/ACMSN/p/10743057.html
Copyright © 2011-2022 走看看