zoukankan      html  css  js  c++  java
  • Luogu P4321 随机漫游

    期望DP要倒着推

    Luogu P4321


    题意

    LOJ #2542

    不一定是树,询问点不一定均为1


    $Solution$ 

    设计一个巧妙的DP状态

    设$ F(S,x)$表示当前在点$ x$已经走遍了$ S$,走完剩下所有点的期望步数

    这样推转移$ DP$的时候一定是从$ F(S|y,y)$转移过来

    容易发现$ S|y$->$S$是不可能会变大的,即这维不可能成环

    因此从大到小枚举$ S$,对当前$ S$,显然比$ S$大的状态已经被计算,暴力$ n^3$高斯消元消出这维就好了

    时间复杂度$ O(2·n·n^3)$

    为什么不直接$ Min-Max$容斥呢

    随机游走

    每次枚举$ S$消出当前$ Min(S,x)$中的x这维

    复杂度不变

    而且很好写啊...


    $ my code$

    #include<ctime>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #define p 998244353
    #define rt register int
    #define ll long long
    using namespace std;
    inline ll read(){
        ll x=0;char zf=1;char ch=getchar();
        while(ch!='-'&&!isdigit(ch))ch=getchar();
        if(ch=='-')zf=-1,ch=getchar();
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return x*zf;
    }
    void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}
    void writeln(const ll y){write(y);putchar('
    ');}
    int k,m,n,x,y,z,cnt,S;
    bool link[20][20];int a[20][20],d[20];
    int inv[20],ans[20][1<<18];
    int ksm(int x,int y=p-2){
        int ans=1;
        for(rt i=y;i;i>>=1,x=1ll*x*x%p)if(i&1)ans=1ll*ans*x%p;
        return ans;
    }
    void gauss(){
        for(rt i=1;i<=n;i++)if(!(S>>i-1&1)){
            for(rt j=i;j<=n;j++)if(a[j][i]){
                if(j!=i)for(rt k=1;k<=n+1;k++)swap(a[i][k],a[j][k]);
                break;
            }
            if(!a[i][i])continue;
            inv[i]=ksm(a[i][i]);
            for(rt j=i+1;j<=n;j++)if(a[j][i]){
                const int x=1ll*a[j][i]*inv[i]%p;
                for(rt k=i;k<=n+1;k++)if(a[i][k])(a[j][k]-=1ll*a[i][k]*x%p)%=p;
            }
        }
        for(rt i=n;i>=1;i--)if(!(S>>i-1&1)){
            ans[i][S]=1ll*a[i][n+1]*inv[i]%p;
            for(rt j=i-1;j>=1;j--)if(a[j][i])(a[j][n+1]-=1ll*ans[i][S]*a[j][i]%p)%=p;
        }
    }
    int ret[20][1<<18];
    int main(){
        n=read();m=read();
        for(rt i=1;i<=m;i++){
            x=read();y=read();d[x]++;d[y]++;
            link[x][y]=link[y][x]=1;
        }
        //Max(S)走遍集合S的时间
        //Min(S)第一次走到S的时间 
        for(S=1;S<(1<<n);S++){
            memset(a,0,sizeof(a));
            for(rt i=1;i<=n;i++){
                if(S>>i-1&1)a[i][i]=1;
                else {
                    for(rt j=1;j<=n;j++)if(link[i][j]&&!(S>>j-1&1))a[i][j]=-1;
                    a[i][i]=d[i];a[i][n+1]+=d[i];
                }
            }
            gauss();
        }
        //Max(S)=sigma Min(T) (-1)|T|+1 
        for(rt i=1;i<=n;i++){
            for(rt j=0;j<(1<<n);j++)if(!(__builtin_popcount(j)&1))ans[i][j]*=-1;
            for(rt j=0;j<n;j++)
            for(rt k=0;k<(1<<n);k++)if(k>>j&1)(ans[i][k]+=ans[i][k^(1<<j)])%=p; 
        }
        for(rt T=read();T;T--){
            n=read();S=0;
            for(rt i=1;i<=n;i++)S|=(1<<read()-1);
            x=read();writeln((ans[x][S]+p)%p);
        }
        return 0;
    }
  • 相关阅读:
    loadrunner数据库MySQL参数化列表乱码问题
    [MySQL]导入导出
    [MySQL]命令行工具和基本操作
    [MySQL]安装和启动
    win7下loadrunner创建mysql数据库参数化问题解决
    Win7-64bit系统下安装mysql的ODBC驱动
    loadrunner个版本历程
    性能分析与调优的原理
    性能分析与调优的原理
    loadrunner解决“服务器正在运行中”方法
  • 原文地址:https://www.cnblogs.com/DreamlessDreams/p/10218806.html
Copyright © 2011-2022 走看看