题解/算法 {E - Random Swaps of Balls}

题解/算法 {E - Random Swaps of Balls}

@LINK: https://atcoder.jp/contests/abc360/tasks/abc360_e;

想了好久才想明白…
一开始确实很难想到思路, 首先你需要枚举一下 然后去挖掘他里面的规律

&Other: 2/(N^2)
&Self: (1 - Avg*(N-1))

最开始序列是[1]234...  (`[]`表示黑球的位置)

第一次操作后的所有情况是:
[1]... (概率是Self)
.[?].. (概率是Other)

假如你此时想顺出上面的思路, 即再枚举下*第二次操作*后的情况, 那么这个就复杂太多了, 因为情况太多了;
比如`[1]...` 他等于`Self*Self + (N-1)*Other*Other`;
`.[?]..`等于`Self*Other + Other*Self + (N-2)*Other*Other`
可以发现 这就复杂的多了... 他应该也是可以做的 即总结出来一个公式出来, 但我们有更好做法;

对于`.[x].`来说 你对他操作一次后 可以分为两种情况, 要么是`.[x].` 要么是`.[?].`(概率相同), 比如`.[x].`的概率是`Y` 那么`.[?].`的概率是`(1-Y)/(N-1)`;
举个例子对于`12[3]4`, 对他操作后 假如得到`12[3]4`的概率是`X` 那么你得到`[1]234 / 1[2]34 / 123[4]`的概率 是相同的 都等于`(1-X)/3`;
这个性质非常重要, 比如答案是`1*P1 + 2*P2 + 3*P3 + ... + N*Pn`, 那么有`P2=P3=...=Pn = (1-P1)/(N-1)`;
换句话说, 你只要求出来`P1`就可以了!

使用数学归纳法
假设操作I次后, 此时:
`.` [1]...的概率是X, 那么对于任意的`.[?].` 他的概率就是`(1-X)/(N-1)`;
任何对他再操作一次 即操作`I+1`次, 此时:
`.` [1]...的概率是`X * &Self + (N-1)*(1-X)/(N-1)*&Other = X*(&Self-&Other) + &Other`;
`.` .[?]..的概率 可以通过`[1]...`的概率推出来;

即每次X *= (Self - Other); X += Other, 重复执行K次;
可以用矩阵乘法优化, 但因为K=1e5不大 我们直接暴力即可;

int N, K; cin>> N>> K;
Mod_ Avg = Mod_(2) / N / N;
Mod_ Self = (Mod_(1) - Avg * (N-1));

Mod_ ans1 = 1;
FOR_( _, 1, K){
    ans1 *= (Self - Avg);
    ans1 += Avg;
}
Mod_ ansI = (Mod_(1) - ans1) / (N-1); // 注意这里`/(N-1)`会存在`/0`的情况 此时`ansI`应该是`0`, 但因为我们`Mod_`是允许除零的 因此没事;

Mod_ ANS = 0;
ANS += (ans1 * 1);
ANS += (ansI * ((2+N)*1LL*(N-1)/2));
cout<< ANS.Value<< '\n';
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值