2017"百度之星"程序设计大赛 - 初赛,A [ hdu 6108 小C的倍数问题 ] [ hdu 6109 数据分割 ] [ hdu 6110 路径交 ] [ hdu 6112 今夕何夕 ] [ hdu 6113 度度熊的01世界 ]?

这套题体验极差。

PROBLEM 1001 - 小C的倍数问题

  OvO http://acm.hdu.edu.cn/showproblem.php?pid=6108

  (2017"百度之星"程序设计大赛 - 初赛(A) - 1001)

  10进制下,各位数和是9的倍数的数能被9整除是因为 10^k-1=能被9整除

  实质上就是10-1的因数有9

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>

using namespace std;

int calcu(int spl)
{
        int i,j,ret=0;
        for(i=1;i*i<=spl;i++)
                if(spl%i==0)
                {
                        ret++;
                        if(i*i!=spl)
                                ret++;
                }
        return ret;
}

int main()
{
        int cas;
        int p;
        cin>>cas;
        while(cas--)
        {
                cin>>p;
                cout<<calcu(p-1)<<endl;
        }
        return 0;
}

  

PROBLEM 1002 - 数据分割

  OvO http://acm.hdu.edu.cn/showproblem.php?pid=6109

  (2017"百度之星"程序设计大赛 - 初赛(A) - 1002)

  每次拿到题目给的2个点,如果这两个点是相等的,则把这两个点所在的并查集合并,否则,找到这两个点的根,然后把把这两个根节点连一条边。

  每次合并并查集的时候,要把相连的边也转移(选择边少的那个并查集转移)。

  每次读入2个点,记录这两个点的具体值,存到栈里,以后每次清空,清空栈里这些值对应的位置即可,这样就算要清空L次也不会超时。

  (思路来源于瞟了一眼某个我忘了在哪里的地方)

  

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>

using namespace std;

const int N=2e5+44;

struct node{
    int u,v;
    int next;
}edge[2*N];

struct clearpair
{
        int a,b;
} ;

queue<clearpair> clearlist;
int cnt,num;
int head[N];
int answer[N],lanswer;
int fa[N],tol[N],hav[N];
int t;

void addedge(int u,int v)
{
    edge[num].u=u;
    edge[num].v=v;
    edge[num].next=head[u];
    head[u]=num++;
}

void changeedge(int id,int u)
{
        edge[id].u=u;
        edge[id].next=head[u];
        head[u]=id;
}

void init(int sz=100000)
{
        t=0;
        num=0;
        for(int i=1;i<=sz;i++)
        {
                head[i]=-1; 
                fa[i]=i;
                tol[i]=1;
        }
        while(!clearlist.empty())
                clearlist.pop();
}

void clear()
{
        clearpair tmp;
        int a,b;
        t=0; num=0;
        while(!clearlist.empty())
        {
                tmp=clearlist.front();
                clearlist.pop();
                head[tmp.a]=-1; fa[tmp.a]=tmp.a; tol[tmp.a]=1;
                head[tmp.b]=-1; fa[tmp.b]=tmp.b; tol[tmp.b]=1;          
        }
}

int fff(int x)
{
        if(fa[x]==x)
                return x;
        fa[x]=fff(fa[x]);
        return fa[x];
}

bool merge(int a,int b)
{
        int v,nxttmp,i,j,pa,pb,pv;
        pa=fff(a); pb=fff(b);
        if(pa==pb) return true;
        if(hav[pa]>hav[pb])
                swap(pa,pb),swap(a,b);
        hav[pb]+=hav[pa];
        fa[pa]=pb;
        for(i=head[pa],nxttmp=edge[i].next;i!=-1;i=nxttmp,nxttmp=edge[i].next)
        {
                v=edge[i].v; pv=fff(v);
                if(pv==pb)
                        return false;
                changeedge(i,pb);
        }
        return true;
}

bool solve(int a,int b,int c)
{
        int pa,pb;
        if(c==0)
        {
                pa=fff(a); pb=fff(b);
                if(pa==pb) return false;
                addedge(pa,pb);
                addedge(pb,pa);
                return true;
        }
        else
                return merge(a,b);
}

int main()
{
        int i,j,a,b,c;
        int T;
        scanf("%d",&T);
        lanswer=0;
        init();
        while(T--)
        {
                t++;
                scanf("%d%d%d",&a,&b,&c);
                clearlist.push((clearpair){a,b});
                if(solve(a,b,c)==false)
                {
                        answer[++lanswer]=t;
                        clear();
                }
        }
        printf("%d\n",lanswer);
        for(i=1;i<=lanswer;i++)
                printf("%d\n",answer[i]);
        return 0;
}

  

  

PROBLEM 1003 - 路径交

  Q∧Q http://acm.hdu.edu.cn/showproblem.php?pid=6110

  (2017"百度之星"程序设计大赛 - 初赛(A) - 1003)

  其实题目求的是[L,R]这个区间的路径的交,(而不是L,R两条的路径交),而且路径交的定义是[L,R]都覆盖的路径,(而不是只要有2条路径覆盖就行),

  开个线段树,线段树中区间[li,ri]对应li~ri这些路径的交。

  求路径交用LCA

  (题意和思路来源于某大佬

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>

using namespace std;

typedef long long ll;

const int MAXN=500044;

int rmq[2*MAXN];//建立RMQ的数组

struct ST
{
    int mm[2*MAXN];//mm[i]表示i的最高位,mm[1]=0,mm[2]=1,mm[3]=1,mm[4]=2
    int dp[MAXN*2][35];
    void init(int n)
    {
        mm[0]=-1;
        for(int i=1;i<=n;i++)
        {
            mm[i]=((i&(i-1))==0?mm[i-1]+1:mm[i-1]);
            dp[i][0]=i;
        }
        for(int j=1;j<=mm[n];j++)
          for(int i=1;i+(1<<j)-1<=n;i++)
             dp[i][j]=rmq[dp[i][j-1]]<rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
    }
    int query(int a,int b)//查询a到b间最小值的下标
    {
        if(a>b)swap(a,b);
        int k=mm[b-a+1];
        return rmq[dp[a][k]]<rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k];
    }
};

struct Node
{
    int to,next,val;
};

struct LCA2RMQ
{
    int n;//结点个数
    Node edge[2*MAXN];//树的边,因为是建无向边,所以是两倍
    int tol;//边的计数
    int head[MAXN];//头结点

    bool vis[MAXN];//访问标记
    int F[2*MAXN];//F是欧拉序列,就是DFS遍历的顺序
    int P[MAXN];//某点在F中第一次出现的位置
    int cnt;

    ST st;
    void init(int n)//n为所以点的总个数,可以从0开始,也可以从1开始
    {
        this->n=n;
        tol=0;
        memset(head,-1,sizeof(head));
    }
    void addedge(int a,int b,int val)//加边
    {
        edge[tol].to=b;
        edge[tol].next=head[a];
        edge[tol].val=val;
        head[a]=tol++;
        edge[tol].to=a;
        edge[tol].next=head[b];
        edge[tol].val=val;
        head[b]=tol++;
    }

    int query(int a,int b)//传入两个节点,返回他们的LCA编号
    {
        return F[st.query(P[a],P[b])];
    }

    void dfs(int a,int lev)
    {
        vis[a]=true;
        ++cnt;//先加,保证F序列和rmq序列从1开始
        F[cnt]=a;//欧拉序列,编号从1开始,共2*n-1个元素
        rmq[cnt]=lev;//rmq数组是深度序列
        P[a]=cnt;
        for(int i=head[a];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(vis[v])continue;
            dfs(v,lev+1);
            ++cnt;
            F[cnt]=a;
            rmq[cnt]=lev;
        }
    }

    void solve(int root)
    {
        memset(vis,false,sizeof(vis));
        cnt=0;
        dfs(root,0);
        st.init(2*n-1);
    }
}lca;

struct Line
{
        int a,b,flag;
} line[MAXN],answer[MAXN],tree[MAXN*3];

ll dep[MAXN];
int lv[MAXN];

bool cmp(int x,int y)
{
        return lv[x]>lv[y];
}

Line merge(Line x,Line y)
{
        Line ret; ret.flag=true;
        if(x.flag==false || y.flag==false)
        {
                ret.flag=false;
                return ret;
        }
        int lcax=lca.query(x.a,x.b),lcay=lca.query(y.a,y.b);
        if(lv[lcax]>lv[lcay])
                swap(x,y),swap(lcax,lcay);
        int lca11=lca.query(x.a,y.a),lca12=lca.query(x.a,y.b),lca21=lca.query(x.b,y.a),lca22=lca.query(x.b,y.b);
        int que[5];
        que[1]=lca11; que[2]=lca12; que[3]=lca21; que[4]=lca22;
        sort(que+1,que+4+1,cmp);
        ret.a=que[1]; ret.b=que[2];
//      cout<<que[1]<<'-'<<que[2]<<endl;
        if(lv[ret.a]<lv[lcax] || lv[ret.b]<lv[lcax] || lv[ret.a]<lv[lcay] || lv[ret.b]<lv[lcay]) ret.flag=false;
//      cout<<ret.a<<' '<<ret.b<<' '<<lcax<<' '<<lcay<<' '<<ret.flag<<endl;
        return ret;
}

void build(int rt,int li,int ri)
{
        if(li==ri)
        {
                tree[rt]=line[ri];
                return ;
        }
        int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
        build(lc,li,mid);
        build(rc,mid+1,ri);
        tree[rt]=merge(tree[lc],tree[rc]);
}

Line query(int rt,int li,int ri,int lq,int rq)  //get Line
{
        bool flag=false;
        Line ret;
        if(lq<=li && ri<=rq)
                return tree[rt];
        int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
        if(mid>=lq)
        {
                flag=true;
                ret=query(lc,li,mid,lq,rq);
        }
        if(mid+1<=rq)
        {
                if(flag==false)
                        ret=query(rc,mid+1,ri,lq,rq);
                else
                        ret=merge(ret,query(rc,mid+1,ri,lq,rq));
        }
        return ret;
}

void getdepth(int rt,int pa,ll depnow,int lvnow)
{
        int i,j,v;
        lv[rt]=lvnow;
        dep[rt]=depnow;
        for(i=lca.head[rt];i!=-1;i=lca.edge[i].next)
        {
                v=lca.edge[i].to;
                if(v==pa) continue;
                getdepth(v,rt,depnow+lca.edge[i].val,lvnow+1);
        }
}

ll getlength(int a,int b)
{
        int c=lca.query(a,b);
        return dep[a]-dep[c]+dep[b]-dep[c];
}

inline void read(int &ret)
{
    int k=0;
    char f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar() )
        if(c=='-')
            f=-1;
    for(;isdigit(c);c=getchar() )
        k=k*10+c-'0';
    ret=k*f;
}

int main()
{
        int i,j,a,b,c,n,m,q;
        ll ans;
        while(scanf("%d",&n)!=EOF)
        {
                lca.init(n);
                for(i=1;i<n;i++)
                {
                        read(a); read(b); read(c);
                        lca.addedge(a,b,c);
                }
                lca.solve(1);
                getdepth(1,-1,0,0);
                read(m);
                for(i=1;i<=m;i++)
                {
                        read(line[i].a); read(line[i].b);
                        line[i].flag=true;
                }
                build(1,1,m);
                read(q);
                for(i=1;i<=q;i++)
                {
                        read(a); read(b);
                        answer[i]=query(1,1,m,a,b);
                }
                for(i=1;i<=q;i++)
                {
        //              cout<<answer[i].a<<' '<<answer[i].b<<endl;
                        if(answer[i].flag)
                                ans=getlength(answer[i].a,answer[i].b);
                        else
                                ans=0;
                        printf("%lld\n",ans);
                }
        }
        return 0;
}

/*

4
1 2 2000000000
2 3 2000000000
1 4 2000000000
4
3 4
3 4
1 4
2 3
4
1 2
3 4
1 3
1 4

*/ 

  

PROBLEM 1005 - 小今夕何夕

  OvO http://acm.hdu.edu.cn/showproblem.php?pid=6112

  (2017"百度之星"程序设计大赛 - 初赛(A) - 1005)

  注意2-29

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

int a,b,c;
int id; 
int inc[3]={1,2};

int jg(int spl)
{
        if(spl%400==0)
                return 1;
        if(spl%100==0)
                return 0;
        if(spl%4==0)
                return 1;
        return 0;
}

int solve()
{
        int ret=a+1,i,j,now=0;
        if(b==2 && c==29)
        {
                id=a+1;
                for(i=id;;i++,ret++)
                {
                        now+=inc[jg(i)];
                        now%=7;
                        if(jg(i) && now==0)
                                return ret;
                }
        }
        id=a;
        if(b>2) id++;
        for(i=id;;i++,ret++)
        {
                now+=inc[jg(i)];
                now%=7;
//              cout<<"ret: "<<ret<<' '<<"i: "<<i<<' '<<"now: "<<now<<endl;
                if(now==0)
                        return ret;
        }
}

int main()
{
        int i,j;
        int T;
        cin>>T;
        while(T--)
        {
                scanf("%d-%d-%d",&a,&b,&c);
                printf("%d\n",solve());
        }
        return 0;
}

  

PROBLEM 1006 - 度度熊的01世界

  OvO http://acm.hdu.edu.cn/showproblem.php?pid=6113

  (2017"百度之星"程序设计大赛 - 初赛(A) - 1006)

  分步慢慢来

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

int n,m;
char mp[111][111];
int tag1[111][111],tag0[111][111];
int dx[5]={0,0,1,-1};
int dy[5]={1,-1,0,0};

bool check(int x,int y)
{
        if(x<=0 || x>n || y<=0 || y>m)
                return false;
        return true;
}

void dfs1(int x,int y)
{
        int i,j,xx,yy;
        tag1[x][y]=1;
        for(i=0;i<4;i++)
        {
                xx=x+dx[i];
                yy=y+dy[i];
                if(check(xx,yy) && tag1[xx][yy]==0 && mp[xx][yy]=='1')
                        dfs1(xx,yy);
        }
}

bool gettag1()
{
        int i,j;
        for(i=1;i<=n;i++)
                for(j=1;j<=m;j++)
                        if(mp[i][j]=='1')
                        {
                                dfs1(i,j);
                                return true;
                        }
        return false;   
}

bool checkblock1()
{
        int i,j;
        for(i=1;i<=n;i++)
                for(j=1;j<=m;j++)
                        if(mp[i][j]=='1' && tag1[i][j]==0)
                                return false;
        return true;
}

int dfs2(int x,int y)
{
        int i,j,xx,yy,ret=1;
        tag0[x][y]=1;
        for(i=0;i<4;i++)
        {
                xx=x+dx[i];
                yy=y+dy[i];
                if(check(xx,yy)==false)
                {
                        ret=0;
                        continue;
                }
                if(tag0[xx][yy] || mp[xx][yy]=='1')
                        continue;
                if(dfs2(xx,yy)==0)
                        ret=0;
        }
        return ret;
}

int getblock0()
{
        int ret=0,i,j;
        for(i=1;i<=n;i++)
                for(j=1;j<=m;j++)
                        if(mp[i][j]=='0' && tag0[i][j]==0)
                                ret+=dfs2(i,j);
        return ret;
}

int solve()
{
        int i,j;
        if(gettag1()==false)
                return -1;
        if(checkblock1()==false)
                return -1;
        int cnt=getblock0();
        if(cnt==0)
                return 1;
        if(cnt==1)
                return 0;
        return -1;
}

void init()
{
        memset(tag1,0,sizeof(tag1));
        memset(tag0,0,sizeof(tag0));
}

int main()
{
        int i,j;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
                for(i=1;i<=n;i++)
                        scanf("%s",mp[i]+1);
                init();
                printf("%d\n",solve());
        }
        return 0;
}