• AGC002 F


    貌似哪里讲过这题。。总之当时掉线了(理解能力又差水平又低选手的日常)。。

    看看题目,应该是DP。

    尝试了几次换状态,毫无思路。那我们就来继续挖掘性质吧。。。为了更直观,我们令第i个出现的球颜色就是i(最后乘个阶乘就成)。那么有:

    1122->0102  

    13223312->00203312

    122132441231344->002102041231344

    我们发现,i个0将序列分成i段,第i段的数字由1...i组成。考虑从1到n依次塞数字,数字i要塞在第i个0后面,因此会有这样的现象。我们尝试DP这个过程。我们发现,从1开始DP将非常恶心,因为前面的数字会影响后面数字的可摆放区间。也就是说,小数字会影响大数字,但大数字却不会影响小数字。于是我们考虑倒过来DP,这就非常舒服了,在放数字i时,第i个白球后面的球个数一定为(n-i)*k个,于是我们就可以愉快组合数了!结案!

    如果直接这样写,那么样例都过不去。。。比如样例中的0021,可以认为出现顺序为1,2,也可以认为出现顺序为2,1。

    因此,除白球外 第1个i球也要放在第1个i+1球前面 否则将当i球、i+1球的实际颜色交换时,该方案会被重复计算。因此,我们要多记一维第一个i球的位置。这个位置必定是直接跟在一串白球后的,所以我们可以这样设计:

    令f[i][j]表示已放完第i...n个球,第i个球前有j个白球的方案数。

    那么有 f[i][j]=f[i+1][j...n]*C(n-j+(n-i+1)*(k-1)-1,k-2))

    前缀和优化一下就好了!

    (注意,当k=1时要特判,直接输出1即可)

    最喜欢这种代码特别短的题了

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define rep(i,l,r) for(int i=l;i<=r;++i)
     5 #define per(i,r,l) for(int i=r;i>=l;--i)
     6 
     7 typedef long long ll;
     8 
     9 const int N=2333,NN=5e6;
    10 const ll p=1e9+7;
    11 
    12 int n,k;
    13 ll jc[NN+3],njc[NN+3],f[N][N],g[N][N];
    14 
    15 ll ksm(ll x,ll w){
    16     ll ans=1;
    17     while(w){
    18         if(w&1ll) (ans*=x)%=p;
    19         (x*=x)%=p;
    20         w>>=1;
    21     }
    22     return ans;
    23 }
    24 
    25 ll C(ll a,ll b){
    26     return (jc[a]*njc[b]%p)*njc[a-b]%p;
    27 }
    28 
    29 int main(){
    30     scanf("%d%d",&n,&k);
    31 
    32     if(k==1){
    33         printf("1
    ");
    34         return 0;
    35     } 
    36 
    37     jc[0]=njc[0]=1;int L=5e6;
    38     rep(i,1,L) jc[i]=(jc[i-1]*i)%p;
    39     rep(i,1,L) njc[i]=ksm(jc[i],p-2);
    40 
    41     rep(j,1,n) g[n][j]=1;f[n][n]=1;
    42     per(i,n-1,1){
    43         rep(j,i,n)
    44             f[i][j]=(g[i+1][j]*C(n-j+(n-i+1)*(k-1)-1,k-2))%p;
    45         per(j,n,1) g[i][j]=(g[i][j+1]+f[i][j])%p;
    46     } 
    47 
    48     ll ans=0;
    49     rep(i,1,n) (ans+=f[1][i])%=p;
    50     (ans*=jc[n])%=p;
    51 
    52     printf("%lld
    ",ans);
    53 
    54     return 0;
    55 }
  • 相关阅读:
    HashTable, HashMap,TreeMap区别
    redis的多线程
    五种I/O模型介绍
    SpringBoot的优点
    spring注解
    三种方法求解两个数组的交集
    数据库七种传播行为
    BETA 版冲刺前准备
    Python学习笔记(二)--变量和数据类型
    事后诸葛亮
  • 原文地址:https://www.cnblogs.com/BLeaves/p/10423706.html
Copyright © 2020-2023  润新知