【jzoj6.24模拟B】

这场真是无聊,搬远古原题……

xjb做了做,(居然没AK真是身败名裂)

A.教主的花园

答案明显具有可二分性,二分答案判定下就行。

#include<bits/stdc++.h>
#define N 100010
using namespace std;
int n,m,a[N];
inline int check(int x){
    int l=1,r=n;int ret=n;
    while(l<=r){
        int mid=(l+r)>>1;
        if(a[mid]<x)l=mid+1;else r=mid-1,ret=mid;
    }
    return ret;
}
inline int dis(int a,int b){a=a-b;if(a<0) return -a;else return a;}
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
int main(){
    n=read();for(int i=1;i<=n;i++)a[i]=read();
    m=read();int x1,y1,x2,y2;
    sort(a+1,a+n+1);
    for(int i=1;i<=m;i++){
        x1=read(),y1=read(),x2=read(),y2=read();
        if((y1<0&&y2<0)||(y1>0&&y2>0)){printf("%d
",dis(y1,y2)+dis(x1,x2));continue;}
        if(x1>x2)swap(x1,x2);int len=(x1+x2)>>1,pos=check(len);
        if(x1<=a[pos]&&a[pos]<=x2){printf("%d
",dis(y1,y2)+dis(x1,x2));continue;}
        int t1=dis(a[pos],x1)+dis(a[pos],x2)+dis(y1,y2),t2=0x7fffffff,t3=0x7fffffff;
        if(pos>1)t2=dis(a[pos-1],x1)+dis(a[pos-1],x2)+dis(y1,y2);
        if(pos<n)t3=dis(a[pos+1],x1)+dis(a[pos+1],x2)+dis(y1,y2);
        if(t1>t2)t1=t2;if(t1>t3)t1=t3;
        printf("%d
",t1);
    }
}

教主泡嫦娥

环形上跑一下dp,四维记录状态。

#include<bits/stdc++.h>
#define N 10010
#define inf 10000000000000007LL
using namespace std;
typedef long long ll;
int a[N],n,m;
ll f[N][2][2],ans=0;
inline ll sqr(ll x){return x*x;}
inline void dfs(){
    f[0][0][1]=f[0][1][1]=inf;
    for(int i=1;i<=n;i++)for(int j=0;j<2;j++)
    if((a[i]<a[i-1])^j){
        f[i][j][0]=f[i-1][j][0]+abs(a[i]-a[i-1]);
        f[i][j][1]=min(f[i-1][j][1],min(f[i-1][j^1][0],f[i-1][j^1][1])+m)+abs(a[i]-a[i-1]);
    }
    else{
        f[i][j][0]=f[i-1][j][0]+sqr(a[i]-a[i-1]);
        f[i][j][1]=min(f[i-1][j][1],min(f[i-1][j^1][0],f[i-1][j^1][1])+m)+sqr(a[i]-a[i-1]);
    }
}
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
int main(){
    n=read();m=read();
    for(int i=0;i<n;i++)a[i]=read();
    a[n]=a[0];memset(f,0,sizeof(f));
    dfs();
    ans=min(min(f[n][0][0],f[n][0][1]),min(f[n][1][0],f[n][1][1]));
    memset(f,0,sizeof(f));f[0][0][0]=inf;dfs();
    ans=min(ans,f[n][1][1]-m);
    memset(f,0,sizeof(f));f[0][1][0]=inf;dfs();
    ans=min(ans,f[n][0][1]-m);
    cout<<ans<<endl;
}

保镖排队:

懒得写了,从网上粘一个解释下来:

于是假设当前有tot个格子,然后自己有j个儿子,因为是可放可不放于是就是C(tot+j,j),这个时候你们就会疑惑了,难道不是C(tot+j-1,j)吗,这不是才是可放可不放的公式吗,但你可能忘记了,自己虽然必须放在最前面,但是总的可放位置仍要把他算进去呀

#include<bits/stdc++.h>
#define N 2010
#define yql 10007
using namespace std;
int f[N][N],dp[N],g[N][N],val[N],n;
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
void calc(int x){
    dp[x]=1;if(!g[x][0]){val[x]=1;return;}
    int tot=0;
    for(int i=g[x][0];i;i--){
        calc(g[x][i]);tot+=val[g[x][i]];
        dp[x]=dp[x]%yql*dp[g[x][i]]%yql*f[tot-1][val[g[x][i]]-1]%yql;
    }
    val[x]=tot+1;
}
inline void pre(){
    f[0][0]=1;
    for(int i=1;i<=2000;i++){
        f[i][0]=1;for(int j=1;j<=i;j++)f[i][j]=(f[i-1][j-1]+f[i-1][j])%yql;
    }
}
int main(){
    pre();int T=read();
    while(T--){
        memset(g,0,sizeof(g));memset(dp,0,sizeof(dp));memset(val,0,sizeof(val));
        n=read();
        for(int i=1;i<=n;i++){
            g[i][0]=read();
            for(int j=1;j<=g[i][0];j++)g[i][j]=read();
        }
        calc(1);
        printf("%d
",dp[1]);
    }
}

教主的别墅

针鸡儿丢人,身败名裂,被卡了一个点

居然都没有AK。

不放代码了,太气了。

原文地址:https://www.cnblogs.com/zcysky/p/7074457.html