• CF453(Div1 简单题解)


    A .Little Pony and Expected Maximum

    pro:给定M,N,表示一个M面的骰子,甩N次,问出现的最大的数的期望。

    sol:容斥,f(i)表示最大数<=i的期望,那么最大数=x的期望就是f(x)-f(x-1);

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=200010;
    double dp[maxn];
    double qpow(double a,int x)
    {
        double res=1.0;while(x){
            if(x&1) res=res*a;
            a=a*a; x>>=1;
        } return res;
    }
    int main()
    {
        int M,N; double ans=0.;
        scanf("%d%d",&M,&N);
        rep(i,1,M) dp[i]=qpow(1.0*i/M,N);
        rep(i,1,M) ans+=(dp[i]-dp[i-1])*i;
        printf("%.10lf
    ",ans);
        return 0;
    }

     

    B .Little Pony and Harmony Chest

    pro:给定数组a[],求一个两两互质的b[],使得abs(a[]-b[])最小,输出一个方案。 N<=100,a[]<=30

    sol:两两互质,表示之前出现的素因子不能出现,而我们发现>60不可能,因为差值会变很大。 所以我们记录<=60的素数,然后状压DP,记录一下来源,最后倒回去输出即可。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=110;
    const int maxm=132000;
    int a[maxn],p[maxn],vis[maxn],tot,cnt;
    int pre[maxn][maxm],now[maxn][maxm],dp[maxn][maxm],fac[maxn];
    vector<int>G[maxm];
    void dfs(int pos,int Now)
    {
        if(pos==0) return ;
        dfs(pos-1,pre[pos][Now]);
        printf("%d ",now[pos][Now]);
    }
    int main()
    {
        int N,M,ans=100000,P;
        memset(dp,0x3f,sizeof(dp)); dp[0][0]=0;
        rep(i,2,57) {
            if(!vis[i]){
                p[tot++]=i;
                for(int j=i+i;j<=57;j+=i) vis[j]=1;
            }
        }
        rep(i,1,57){
            rep(j,0,tot-1){
                if(i%p[j]==0){
                    fac[i]|=(1<<j);
                }
            }
        }
        M=(1<<tot)-1;
        rep(i,0,M) rep(j,1,57)
          if(!(fac[j]&i)) G[i].push_back(j),cnt++;
        scanf("%d",&N);
        rep(i,1,N) scanf("%d",&a[i]);
        rep(i,1,N){
            rep(j,0,M) {
                for(int k=0;k<G[j].size();k++){
                    int v=G[j][k];
                    if(dp[i][j|fac[v]]>dp[i-1][j]+abs(a[i]-v)){
                        dp[i][j|fac[v]]=dp[i-1][j]+abs(a[i]-v);
                        pre[i][j|fac[v]]=j;
                        now[i][j|fac[v]]=v;
                    }
                }
            }
        }
        rep(i,0,M) if(dp[N][i]<ans) ans=dp[N][i],P=i;
        dfs(N,P);
        return 0;
    }

    C .Little Pony and Summer Sun Celebration

    pro:给定N点M边的无向图(不一定连通),然后给没给点限制一个0或1,表示经过点的奇偶,让你找一条路径,满足路径长度<=N*4,而且满足奇偶要求。

    sol:我们DFS,如果儿子的奇偶性未满足,满足我们再走一遍(fa->son->fa)即可,发现一定可以构造好。。。然后就是要求的奇数的点一定要连通。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2000010;
    int Laxt[maxn],Next[maxn],To[maxn],d[maxn],cnt;
    int a[maxn],b[maxn],tot,vis[maxn],t[maxn],F=1;
    void add(int u,int v)
    {
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;
    }
    void dfs(int u,int f)
    {
        vis[u]=1; t[u]^=1;
        for(int i=Laxt[u];i;i=Next[i]){
            int v=To[i];
            if(v!=f&&!vis[v]){
                tot++; a[tot]=u; b[tot]=v;
                dfs(v,u);
                tot++; a[tot]=v; b[tot]=u; t[u]^=1;
                if(d[v]!=t[v]){
                    tot++; a[tot]=u; b[tot]=v; t[v]^=1;
                    tot++; a[tot]=v; b[tot]=u; t[u]^=1;
                }
            }
        }
    }
    int main()
    {
        int N,M,u,v,root=-1;
        scanf("%d%d",&N,&M);
        rep(i,1,M){
            scanf("%d%d",&u,&v);
            add(u,v); add(v,u);
        }
        rep(i,1,N) scanf("%d",&d[i]);
        rep(i,1,N) if(d[i]==1) root=i;
        if(root==-1) return puts("0"),0;// root=1;
        dfs(root,0);
        rep(i,1,N) if(!vis[i]&&d[i]==1) F=0;
        if(!F) return puts("-1"),0;
        if(t[root]!=d[root]) tot--;
        printf("%d
    ",tot+1);
        printf("%d ",root);
        rep(i,1,tot) printf("%d ",b[i]);
        return 0;
    }

     

    D .Little Pony and Elements of Harmony

    FWT,不会,占位。

    E .Little Pony and Lord Tirek

    题意:N个马,给定了开始的能量值s[],以及能力上限m[],以及单位时间的能力上升值r[]。Q次操作,每次给出[L,R],吸走这个区间的马的能力和sum,求sum,马的能力被吸走后变为0。

    思路:想不到线段树就可以做。。。。tql ,注意r可能为0,不要除0,免得RE。

    主要一点就是,区间更新,区间时间一样了,我们就可以均摊复杂度了,即tag相同的区间利用预处理,不同的继续下推。

    我们先预处理,把每个节点按照达到上限的时间排序,然后得到前缀和,用前缀和来快速得到,这个区间给定时间差后的sum。

    时间复杂度O(N(logN)^2),空间O(NlogN);

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=100010;
    const int inf=2e9;
    int s[maxn],m[maxn],r[maxn],t[maxn],vis[maxn<<2];
    int T[19][maxn]; ll pre[19][maxn],v[20][maxn];
    struct in{
        int m,r,t;
        in(){}
        in(int mm,int rr,int tt):m(mm),r(rr),t(tt){}
        bool friend operator<(in w,in v){
            return w.t<v.t;
        }
    }fcy[maxn];
    void build(int dep,int Now,int L,int R)
    {
        rep(i,L,R) fcy[i]=in(m[i],r[i],t[i]);
        sort(fcy+L,fcy+R+1);
        rep(i,L,R){
            T[dep][i]=fcy[i].t;
            pre[dep][i]=fcy[i].m;
            v[dep][i]=fcy[i].r;
            if(i>L){
                pre[dep][i]+=pre[dep][i-1];//满的部分前缀和
                v[dep][i]+=v[dep][i-1]; //速度前缀和
            }
        }
        if(L==R){ vis[Now]=0; return; }
        vis[Now]=-1; int Mid=(L+R)>>1;
        build(dep+1,Now<<1,L,Mid);
        build(dep+1,Now<<1|1,Mid+1,R);
    }
    ll query(int dep,int Now,int L,int R,int ql,int qr,int times)
    {
        if(vis[Now]==0){
            vis[Now]=times;
            if(s[L]+1LL*times*r[L]>=m[L]) return 1LL*m[L];
            return 1LL*s[L]+times*r[L];
        }
        if(ql<=L&&qr>=R&&vis[Now]>0){
            int p=upper_bound(T[dep]+L,T[dep]+R+1,times-vis[Now])-T[dep]; p--;
            ll res=((p>=L)?pre[dep][p]:0); //满的
            res+=(v[dep][R]-((p>=L)?v[dep][p]:0))*(times-vis[Now]); //未满
            vis[Now]=times;
            return res;
        }
        if(vis[Now]>=0) vis[Now<<1]=vis[Now<<1|1]=vis[Now];
        int Mid=(L+R)>>1; ll res=0;
        if(ql<=Mid) res+=query(dep+1,Now<<1,L,Mid,ql,qr,times);
        if(qr>Mid) res+=query(dep+1,Now<<1|1,Mid+1,R,ql,qr,times);
        if(vis[Now<<1]==vis[Now<<1|1])
           vis[Now]=vis[Now<<1]; else vis[Now]=-1;
        return res;
    }
    int main()
    {
        int N,M,ts,L,R;
        scanf("%d",&N);
        rep(i,1,N){
            scanf("%d%d%d",&s[i],&m[i],&r[i]);
            if(!r[i]) t[i]=inf;
            else t[i]=m[i]/r[i]+(m[i]%r[i]?1:0);
        }
        build(1,1,1,N);
        scanf("%d",&M);
        rep(i,1,M){
            scanf("%d%d%d",&ts,&L,&R);
            ll ans=query(1,1,1,N,L,R,ts);
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    5.Hiveguigun滚(ノ`Д)ノ竟然竞争谨慎谨慎谨慎哈喇子罢工八公
    4.HadoopMapRe程序设计
    3.MapReduce原理和Yarn
    java注解
    各种操作系统远程windows服务器
    protocol-buffers
    反向生成实体类
    java 反射
    web api 返回数据
    Newtonsoft.Json
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10472925.html
Copyright © 2020-2023  润新知