屯题2

1.BZOJ1026

数位DP裸题,纯属为了回忆一下而做的

代码如下:

#include<bits/stdc++.h>
#define int long long
#define N 55
using namespace std;
int L,R,a[N],dp[N][N];
int dfs(int pos,int last,bool limit,bool lead){
    if (pos==0) return 1;
    if (limit&&lead&&dp[pos][last]) return dp[pos][last];
    int ans=0,up;
    if (limit) up=9;else up=a[pos];
    for (int i=0;i<=up;i++){
        if (abs(i-last)<2&&lead) continue;
        ans=ans+dfs(pos-1,i,(limit|(i!=a[pos])),(lead|(i!=0)));
    }
    if (limit&&lead) dp[pos][last]=ans;return ans;
}
inline int solve(int x){
    int xb=x;int tot=0;
    while (xb){
        a[++tot]=xb%10;
        xb/=10;
    }
    memset(dp,0,sizeof(dp));
    return dfs(tot,0,0,0);
}
signed main(){
    scanf("%lld%lld",&L,&R);
    printf("%lld\n",solve(R)-solve(L-1));
    return 0;
}

 2.BZOJ4484

个人感觉还是有点难想到拓扑序的

跑出拓扑序,然后倒着跑

跑的时候用bitset维护连通性

代码如下:

#include<bits/stdc++.h>
#define pi pair<int,int>
#define mk make_pair
#define N 30005
using namespace std;
int n,m,x,y,kk,ans,left1,right1,q[N*10],ru[N*10],head[N*10],dis[N*10];
bitset<N>bit[N];
struct Edge{int nxt,to;}e[N*10];
inline void link(int x,int y){e[++kk].nxt=head[x];e[kk].to=y;head[x]=kk;}
inline void topsort(){
    left1=1,right1=0;
    for (int i=1;i<=n;i++) if (!ru[i]) q[++right1]=i;
    while (left1<=right1){
        int u=q[left1++];
        for (int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            ru[v]--;
            if (!ru[v]) q[++right1]=v;
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        link(x,y);ru[y]++;
    }
    topsort();ans=0;
    for (int i=right1;i;i--){
        int u=q[i];
        for (int j=head[u];j;j=e[j].nxt){
            int v=e[j].to;
            bit[u]|=bit[v];
        }
        for (int j=head[u];j;j=e[j].nxt){
            int v=e[j].to;
            if (bit[u][v]) ans++;
            bit[u][v]=1;
        }
    }
    printf("%d\n",ans);
    return 0;
}

 3.BZOJ4774

斯坦纳树入门题,通过这个我终于学会了斯坦纳数(现在才会,真是菜

在之前的博客中有很详细的解释

代码如下:

/*https://blog.csdn.net/wu_tongtong/article/details/78992913*/
#include<bits/stdc++.h>
#define N 40005
using namespace std;
int n,m,d,x,y,z,cnt,inf,kk,left1,right1,head[N],q[N*400],g[N],use[N],dp[N][1<<8];
struct Edge{int nxt,to,step;}e[N];
inline void link(int x,int y,int z){e[++kk].nxt=head[x];e[kk].to=y;e[kk].step=z;head[x]=kk;}
inline void spfa(int S){
    while (left1<=right1){
        int u=q[left1++];
        for (int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if (dp[v][S]>dp[u][S]+e[i].step){
                dp[v][S]=dp[u][S]+e[i].step;
                q[++right1]=v;
            }
        }
    }
}
inline bool check(int S1){
    for (int i=0;i<d;i++){
        if (S1>>i&1)
            if (!(S1>>(d+i)&1)) return 0;
    }
    return 1;
}
int main(){
    scanf("%d%d%d",&n,&m,&d);
    for (int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        link(x,y,z);link(y,x,z);
    }
    memset(g,127/3,sizeof(g));
    memset(dp,127/3,sizeof(dp));inf=dp[0][0];
    for (int i=1;i<=d;i++) use[++cnt]=i;
    for (int i=n;i>=n-d+1;i--) use[++cnt]=i;
    for (int i=1;i<=cnt;i++) dp[use[i]][1<<(i-1)]=0;
    for (int j=0;j<(1<<cnt);j++){
        for (int i=1;i<=n;i++)
            for (int k=(j-1)&j;k;k=(k-1)&j)
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[i][j^k]);
        left1=1;right1=0;
        for (int i=1;i<=n;i++) if (dp[i][j]<inf) q[++right1]=i;
        spfa(j);//g[j]=inf;
        for (int i=1;i<=n;i++) g[j]=min(g[j],dp[i][j]);
    }
    for (int i=0;i<(1<<cnt);i++)
        for (int j=(i-1)&i;j;j=(j-1)&i) if (check(j)&&check(i^j)) g[i]=min(g[i],g[j]+g[i^j]);
    if (g[(1<<cnt)-1]>=inf) puts("-1");
    else printf("%d\n",g[(1<<cnt)-1]);
    return 0;
}

 4.codechef A humongous Query

这题真的高的不行,无法谈笑风生啊

考虑dp,我们发现这玩意可以倒退回去

所以枚举dp的值,然后倒退判断是否符合初始化即可

太高了

#include<bits/stdc++.h>
#define inf 1000000000
#define N 50005
using namespace std;
int T,X;char s[N];
int main(){
    scanf("%d",&T);
    while (T--){
        scanf("%s",s+1);
        scanf("%d",&X);
        int n=strlen(s+1);
        int ans=inf;
        for (int i=0;i<=X;i++){
            int f0=X,f1=i;
            int tot=0;bool flag=1;
            for (int j=n;j>1;j--){
                if (f1<0||f0<0){flag=false;break;}
                if (f0>=f1){
                    f0=f0-f1;
                    if (s[j]!='0') tot++;
                }
                else {
                    f1=f1-f0-1;
                    if (s[j]!='1') tot++;
                }
            }
            f1=f1-f0-1;
            if (flag&&f1==0&&f0==0) ans=min(ans,tot);
        }
        if (ans==inf) puts("NO");
        else puts("YES"),printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2018-09-15 17:01  longint  阅读(132)  评论(0编辑  收藏  举报