zoukankan      html  css  js  c++  java
  • bzoj4872

    期望dp

    首先如果k=n的话,那么我们从后往前,只要看到两者的灯就关上,因为如果当前一个灯没关上,那么之后不可能关上,一个灯只能由自己倍数控制,所以这样我们就计算出了需要操作的次数,如果这个次数<=k,直接把这个步数乘上阶乘就可以了。

    考虑期望的部分,设f[i]为当前状态下还需要操作i次结束的期望步数,f[i]=(i/n)*(f[i-1]+1)+(1-i/n)*(f[i+1]+1) 就是有i/n的概率会关上一盏不需要关上的灯,期望步数加上还需要i-1步的期望加上走一步乘上概率

    但是这个东西只能高斯消元求,肯定跑不过去,那么我们差分一下,g[i]=f[i]-f[i-1]

    得出g[i]=(g[i+1]*(n-i)+n)/i

    因为g是差分得出的,所以最终答案是g[1]+...+g[tot],tot是最初状态需要的步数。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 100010, mod = 100003;
    int n, k, tot;
    int v[N];
    ll fac = 1, sum;
    ll g[N];
    ll power(ll x, ll t)
    {
        ll ret = 1;
        for(; t; t >>= 1, x = x * x % mod) if(t & 1) ret = ret * x % mod;
        return ret;
    }
    int main()
    {
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; ++i) 
        {
            scanf("%d", &v[i]);
            fac = fac * (ll)i % mod;
        }
        for(int i = n; i; --i) if(v[i])
        {
            for(int j = 1; j * j <= i; ++j) if(i % j == 0)
            {
                v[j] ^= 1;
                if(j * j != i) v[i / j] ^= 1;
            }
            ++tot;
        } 
        if(k >= tot)
        {
            printf("%lld
    ", fac * tot % mod);
            return 0;
        }
        g[n + 1] = 1e9;
        for(int i = n; i; --i)
        {
            if(i <= k) g[i] = 1;
            else g[i] = ((ll)(n - i) * g[i + 1] + n) % mod * power(i, mod - 2) % mod;
    //        sum = (sum + g[i]) % mod;
        }
        for(int i = 1; i <= tot; ++i) sum = (sum + g[i]) % mod;
        sum = sum % mod * fac % mod;
        printf("%lld
    ", (sum + mod) % mod); 
        return 0;
    }
    View Code
  • 相关阅读:
    本周学习小结(04/11
    学习笔记之知识图谱 (Knowledge Graph)
    本周学习小结(28/10
    本周学习小结(21/10
    条件分页 代替离线查询
    Apache POI 一键上传(导入excel文件到数据库)
    easyui 菜单按钮&提示框
    Jquery ztree树插件
    Jquery ztree树插件2
    ui
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7221604.html
Copyright © 2011-2022 走看看