• E. Wish I Knew How to Sort codeforces1754E


    Problem - E - Codeforces

    题目大意:有一个长度为n的只含有0和1的数组,要求把数组按从小到大排序,但每次操作只能随机选取一前一后两个位置并交换这两个位置上的数,问期望的交换次数是多少

    1<=n<=2e5.

    思路:首先,从n个数中随机选两个,一共有c(n,2)种可能,然后排完序后的数组是形如00111这样的,所以我们统计数组0的数量,然后统计应该是0的位置上有几个1,这样就得到了我们需要的最少操作次数,对于每一次操作,如果当前还至少剩余i次操作需要进行,那么转移到i-1就是正好要选出i个1和i个0也就是i*i中可能,所以i转移到i-1的概率为p=i*i/c(n,2),进行无效操作也就是转移到i的概率是1-p,所以dp[i]=i*i/c(n,2)*dp[i-1]+1-i*i/c(n,2)*dp[i]+1,化简得dp[i]=dp[i-1]+1/p,所以我们最终要求的初始剩余cnt1次操作时的期望按照上述转移式展开化简就等于将每一步的1/p累加

    1. #include
    2. #include
    3. using namespace std;
    4. const int N = 2e5 + 5, MOD = 998244353;
    5. typedef long long ll;
    6. int a[N];
    7. ll qpow(ll a, ll b)
    8. {//快速幂求逆元
    9. ll ret = 1;
    10. while (b)
    11. {
    12. if (b & 1)
    13. {
    14. ret = ret * a % MOD;
    15. }
    16. a = a * a % MOD;
    17. b >>= 1;
    18. }
    19. return ret % MOD;
    20. }
    21. int main()
    22. {
    23. int t;
    24. cin >> t;
    25. while (t--)
    26. {
    27. ll n;
    28. scanf("%lld", &n);
    29. int cnt0 = 0;
    30. for (int i = 1; i <= n; i++)
    31. {
    32. scanf("%d", &a[i]);
    33. if (!a[i])
    34. {
    35. cnt0++;//统计0的个数
    36. }
    37. }
    38. int cnt1 = 0;
    39. for (int i = 1; i <= cnt0; i++)
    40. {
    41. if (a[i])
    42. {
    43. cnt1++;//统计应该是0的位置有多少1
    44. }
    45. }
    46. ll ans = 0;
    47. ll temp = n * (n - 1) / 2 % MOD;//c(n,2)
    48. for (ll i = 1; i <= cnt1; i++)
    49. {
    50. ans = (ans + qpow(i * i % MOD, MOD - 2) * temp % MOD) % MOD;//每一步概率之和
    51. }
    52. printf("%lld\n", ans);
    53. }
    54. return 0;
    55. }

     

     

  • 相关阅读:
    Python爬虫不太冷系列一:初识爬虫
    json/js对象的key有什么区别?
    ​LeetCode解法汇总2864. 最大二进制奇数
    计组 | 【三 存储系统】强化阶段应用题与例题类型总结
    Linux修改24小时制中国时区
    GBASE 8C——SQL参考6 sql语法(5)
    DP - OOD - ISP
    【论文分享】Fuzzing: A Survey for Roadmap
    实验2.6.3 函数拓展练习
    代码命名规范
  • 原文地址:https://blog.csdn.net/ashbringer233/article/details/127753780