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;
}
原文地址:https://www.cnblogs.com/hua-dong/p/10472925.html