zoukankan      html  css  js  c++  java
  • BZOJ_4872_[Shoi2017]分手是祝愿_概率与期望

    BZOJ_4872_[Shoi2017]分手是祝愿_概率与期望

    Description

    Zeit und Raum trennen dich und mich.
    时空将你我分开。B 君在玩一个游戏,这个游戏由 n 个灯和 n 个开关组成,给定这 n 个灯的初始状态,下标为
    从 1 到 n 的正整数。每个灯有两个状态亮和灭,我们用 1 来表示这个灯是亮的,用 0 表示这个灯是灭的,游戏
    的目标是使所有灯都灭掉。但是当操作第 i 个开关时,所有编号为 i 的约数(包括 1 和 i)的灯的状态都会被
    改变,即从亮变成灭,或者是从灭变成亮。B 君发现这个游戏很难,于是想到了这样的一个策略,每次等概率随机
    操作一个开关,直到所有灯都灭掉。这个策略需要的操作次数很多, B 君想到这样的一个优化。如果当前局面,
    可以通过操作小于等于 k 个开关使所有灯都灭掉,那么他将不再随机,直接选择操作次数最小的操作方法(这个
    策略显然小于等于 k 步)操作这些开关。B 君想知道按照这个策略(也就是先随机操作,最后小于等于 k 步,使
    用操作次数最小的操作方法)的操作次数的期望。这个期望可能很大,但是 B 君发现这个期望乘以 n 的阶乘一定
    是整数,所以他只需要知道这个整数对 100003 取模之后的结果。

    Input

    第一行两个整数 n, k。
    接下来一行 n 个整数,每个整数是 0 或者 1,其中第 i 个整数表示第 i 个灯的初始情况。
    1 ≤ n ≤ 100000, 0 ≤ k ≤ n;

    Output

    输出一行,为操作次数的期望乘以 n 的阶乘对 100003 取模之后的结果。

    Sample Input

    4 0
    0 0 1 1

    Sample Output

    512
     

    状态神了,想了很长时间才明白。
    可以发现每个灯控制的都是不同的,并且不会有几种操作拼起来和另外的一些操作等价。
    这就说明每个状态到结束状态还剩的步骤是固定的。即‘正确’的操作是确定的。
    那么我们只需要知道当前状态到结束状态还剩几步正确的操作,而不需要知道确切的状态。
    接着,考虑差分设状态,设F[i]为从 i步错误的状态 到 i-1步错误的状态 所需要的步数的期望。
    这样转移就没有环了,F[i]=i/n+(n-i)/n*(1+F[i+1]+F[i])。化简一下可得F[i]=((n-i)*F[i+1]+n)/i。
    然后求个逆元从大到小递推即可。注意只需要推到F[k]。
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 100050
    typedef long long ll;
    ll mod=100003,b[N];
    int n,v[N],degree,num;
    ll qp(ll x,ll y) {
        ll re=1;
        while(y) {
            if(y&1ll) re=re*x%mod;
            x=x*x%mod;
            y>>=1ll;
        }
        return re;
    }
    int main() {
        scanf("%d%d",&n,&degree);
        int i,j;
        for(i=1;i<=n;i++) scanf("%d",&v[i]);
        for(i=n;i;i--) {
            if(v[i]) {
                for(j=1;j*j<=i;j++) {
                    if(i%j==0) {
                        v[j]^=1;
                        if(j*j!=i) v[i/j]^=1;
                    }
                }
                num++;
            }
        }
        for(i=n;i;i--) {
            b[i]=(b[i+1]*(n-i)%mod+n)%mod*qp(1ll*i,mod-2)%mod;
        }
        ll ans=0;
        if(num<=degree) ans=num;
        else {
            for(i=num;i>degree;i--) {
                ans=(ans+b[i])%mod;
            }
            ans=(ans+degree)%mod;
        }
        for(i=1;i<=n;i++) {
            ans=ans*i%mod;
        }
        printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    【JZOJ3188】找数【数论,数学】
    【JZOJ3187】的士【模拟】
    【JZOJ3187】的士【模拟】
    【洛谷P1641】生成字符串【数论,数学】
    【洛谷P1896】互不侵犯【状压dp】
    聚集索引与非聚集索引
    哈希索引
    索引能提高检索速度,降低维护速度
    MySQL索引基本知识
    注解
  • 原文地址:https://www.cnblogs.com/suika/p/8742828.html
Copyright © 2011-2022 走看看