Generation I(排列组合问题)

原题:牛客网暑期ACM多校训练营(第六场)C

这里写图片描述

题意:

有n个set(元素没有数量之分),有无限个1~m,第i次操作可以从中选一个元素往set i~n里面插入
求有多少种可能结果(只要有一个set不是完全相同)

解析:

方案问题之所以复杂往往是缺失了正确的理解,就像上一篇讲的矩阵转图论再转dp一样

这道题如果从前往后推或者接下去找规律的话就很难做了,换种思路,如果我们选出总共i种元素来放的话,每种元素只有第一次放才有作用,所以我们计算第一次出现位置即可

对于n,m选i种元素的情况

  1. m选i:C(m,i)
  2. n选i放:C(n,i)
  3. i种元素顺序:A(i,i)

得出:Π(m-i+1~m)*Π(n-i+1~n)/i!

但是这个只是理想情况而已,因为题目的意思,第一个放的位置并无影响,所以所有情况都*i/n

得出:Π(m-i+1~m)*Π(n-i+1~n-1)/(i-1)!

当然,我们只要对于i==1的情况赋特殊初值就可以解决这个问题

而i的范围是1~min(m,n),对于不同的i是可以递推的,所以时间就是min(m,n)了

代码:


D read(){ D ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
const D mod=998244353;
const int N=1e6;
D inv[N+9];
void ininv(){
    mmm(inv,0);
    inv[1] = 1;inv[0]=1;
    for(int i = 2; i <= N+1 ; i++)
    inv[i] = ( mod - mod / i ) * inv[ mod % i ] % mod;
}

int main(){
    ininv();
    int t=read(),cas=0;
    while(t--){
        D n=read(),m=read();m=m%mod,n=n%mod;
        D i,ans=m,sum =m;

        for(i=2;i<=min(n,m);i++){
            sum=sum*(m-i+1)%mod*(n-i+1)%mod*inv[i-1]%mod;
            ans=(ans+sum)%mod;
        }
        printf("Case #%d: %lld\n", ++cas, ans);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值