zoukankan      html  css  js  c++  java
  • P6835 [Cnoi2020]线形生物

    链接

    做期望还不是很熟练啊,这个题做了一个小时才做出来。

    想必各位大佬都是秒切。

    这个题是一个不是很裸的转移带环处理,但实际上还是很裸。

    我们设 (f_i) 表示现在在 (i) ,想要到 (n) 的期望步数。

    我们把样例 (4) 画一下,如图:

    不难发现有一下转移:

    [egin{cases} f_1=frac12 (f_1+1+f_2+1) \ f_2=f_3+1\ f_3=frac{1}{2}(f_4+1+f_1+1)\ f_4=frac{1}{2}(f_5+1+f_2+1)\ f_5=frac{1}{2}(f_6+1+f_1+1) end{cases} ]

    (f_6) 在画图的时候忘画上去了。以及这个东西画不出来自环。请各位自行脑补

    然后我们就能够发现,(f_1) 可以用 (f_3) 表示出来,同样的 (f_2) 可以用 (f_4) 表示出来,(f_1) 可以用 (f_5) 表示出来。

    比如上面这个例子,就有:

    [egin{cases} f_1=f_2+2\ f_2=f_3+1\ f_3=f_4+5\ f_4=f_5+8\ f_5=f_4+19 end{cases} ]

    然后我们就可以累积后面的那个数以得到答案。

    至于求解后面的那个数,我们把图建出来,用前缀和维护即可。

    代码:

    #include<bits/stdc++.h>
    #define dd double
    #define ld long double
    #define ll long long
    #define uint unsigned int
    #define ull unsigned long long
    #define N 1000100
    #define M 3000200
    using namespace std;
    
    const int INF=0x3f3f3f3f;
    const ll mod=998244353;
    
    template<typename T> inline void read(T &x) {
        x=0; int f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        x*=f;
    }
    
    struct edge{
        int to,next;
        inline void intt(int to_,int ne_){
            to=to_;next=ne_;
        }
    };
    edge li[M];
    int head[N],tail;
    
    inline void add(int from,int to){
        li[++tail].intt(to,head[from]);
        head[from]=tail;
    }
    
    // ll inv[N];
    
    // inline ll ksm(ll a,ll b,ll mod){
    //     ll res=1;
    //     while(b){
    //         if(b&1) (res*=a)%=mod;
    //         a=a*a%mod;b>>=1;
    //     }
    //     return res;
    // }
    
    ll id,n,m,sum[N],c[N],ans;
    
    int main(){
        freopen("my.in","r",stdin);
        freopen("my.out","w",stdout);
        read(id);read(n);read(m);
        for(int i=1;i<=n;i++) add(i,i+1);
        for(int i=1;i<=m;i++){
            int from,to;read(from);read(to);
            add(from,to);
        }
        for(int i=1;i<=n;i++){
            for(int x=head[i];x;x=li[x].next){
                int to=li[x].to;
                if(to!=i+1) c[i]+=(sum[i-1]-sum[to-1]+1)%mod;
                else c[i]+=1;
                c[i]%=mod;
            }
            sum[i]=sum[i-1]+c[i];sum[i]%=mod;
        }
        for(int i=1;i<=n;i++) printf("i:%d c:%lld
    ",i,c[i]);putchar('
    ');
        for(int i=n;i>=1;i--){
            ans+=c[i];ans%=mod;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    

    时间复杂度 (O(n+m))

  • 相关阅读:
    通道的理解
    系统安装-老毛桃
    ppt文字变图形
    关于android出现不能下载相关依赖包,解决办法
    关于字体图标的问题
    初始化小程序的第一个问题
    css盒子垂直居中的5种方式
    关于网页图标的引用--bootstrap4和ElementUI
    安装vue-cli缓慢问题
    基于SSM在线考试系统的核心功能,随机组卷的实现
  • 原文地址:https://www.cnblogs.com/TianMeng-hyl/p/15005073.html
Copyright © 2011-2022 走看看