9.18 题解?

100+100+10=210 rank 1
T1,醉了,考试时对拍平均1分钟一个错,真爽……暴力枚举约数判断就好了,从根dfs,当

size[v]modD+1>D
时 return;

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 1000005
using namespace std;

int dd[100005],vis[100005],tot,n,ans;

int e=1,head[N];
struct edge{
    int u,v,next;
}ed[2*N];
void add(int u,int v){
    ed[e].u=u;ed[e].v=v;
    ed[e].next=head[u];head[u]=e++;
}

int fa[N],size[N];
void dfs(int x){
    for(int i=head[x];i;i=ed[i].next){
        int v=ed[i].v;
        if(v==fa[x])continue;
        fa[v]=x; dfs(v);
        size[x]+=size[v];
    }size[x]++;
}

void divid(int x){
    for(int i=2;i*i<=x;i++){
        if(x%i==0){
            dd[++tot]=i;
            if(i*i!=x)dd[++tot]=x/i;
        }
    }
}

bool lose;
void dfs1(int x,int p){
    if(lose==1)return;
    if(size[x]<=p)return;
    int r=1,ful=0;
    for(int i=head[x];i;i=ed[i].next){
        int v=ed[i].v;
        if(v==fa[x])continue;
        int mm=size[v]%p;
        if(mm){
            if(ful){lose=1;return;}
            else{
                if((r+mm)<=p){
                    r+=mm;
                    if(r==p)ful=1;
                }
                else{lose=1;return;}
            }
        }
    }
    for(int i=head[x];i;i=ed[i].next){
        int v=ed[i].v;
        if(v==fa[x])continue;
        dfs1(v,p);
    }
}
bool check(int x){
    lose=0; dfs1(1,x);
    return !lose;
}

int main(){
    //freopen("test.in","r",stdin);
    //freopen("my.out","w",stdout);
    scanf("%d",&n);
    if(n==1){printf("1
");return 0;}
    divid(n); 
    sort(dd+1,dd+tot+1);
    for(int i=1,u,v;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    dfs(1);
    ans=2;
    for(int i=tot;i>=1;i--)
        if(check(dd[i]))ans++;
    printf("%d
",ans);
    return 0;
}

T2,二分,暴力判断,我是枚举1所在块的右端点,暴力往左拓展,再判断.

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 50005
using namespace std;
int n,m,a[N],sum[N],maxt,ANS;
bool check(int x){
    int i=n,be=1,en,now,u,tot;
    en=n;
    while(sum[en]+a[1]<=x)en--;
    tot=sum[en+1]+a[1];
    while(1){
        while(sum[1]-sum[be+1]+sum[en+1]<=x)be++;
        be--; tot=sum[en+1]+sum[1]-sum[be+1];
        u=1;now=be;
        while(now<en){
            for(i=now;i<=en+1&&sum[now+1]-sum[i+1]<=x;i++);
            now=i-1; u++;
            if(u>m)break;
        }
        if(u<=m)return 1;
        for(i=en+1;i<=n+1&&tot+a[be+1]-(sum[en+1]-sum[i])>x;i++);
        be++; en=i-1;
        if(en>n)break;
    }
    return 0;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        maxt=max(maxt,a[i]);
    }
    for(int i=n;i>=1;i--)sum[i]=sum[i+1]+a[i];
    int l=maxt,r=sum[1],mid;
    while(l<=r){
        mid=(l+r)>>1;
        if(check(mid)){ANS=mid;r=mid-1;}
        else l=mid+1;
    }
    printf("%d
",ANS);
    return 0;
}

T3,对题意理解不到位,没有想到建图。。而且被老于放了波毒。
建图+spfa

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 55
using namespace std;

int e=1,head[N*N];
struct edge{
    int u,v,w,next;
}ed[2*8*N*N];
void add(int u,int v,int w){
    ed[e].u=u; ed[e].v=v; ed[e].w=w;
    ed[e].next=head[u]; head[u]=e++;
}


int dx[8]={-2,-2,-1,-1,1,1,2,2},dy[8]={-1,1,-2,2,-2,2,-1,1};
int n,m,a[N][N],id[N][N],sx,sy,tx,ty,tot;

bool jj(int x,int y){
    if(x<=0||y<=0||x>n||y>m)return 0;
    return 1;
}
bool bo[N*N],vis[N][N];
int qq[N*N],cnt;
bool road[N*N][N*N];

void dfs(int x,int y){
    for(int i=0;i<8;i++){
        int nx=x+dx[i],ny=y+dy[i];
        if(jj(nx,ny)&&a[nx][ny]==1&&!bo[id[nx][ny]]){
            bo[id[nx][ny]]=1;
            dfs(nx,ny);
        }
        if(jj(nx,ny)&&!a[nx][ny]&&!vis[nx][ny]){
            vis[nx][ny]=1;
            qq[++cnt]=id[nx][ny];
        }
    }
}

int dis[N*N],g[N*N];
void spfa(){
    memset(bo,0,sizeof bo);
    memset(dis,0x3f,sizeof dis);
    int q[N*N],h=1,t=1;q[1]=id[sx][sy];
    g[id[sx][sy]]=1;dis[id[sx][sy]]=0;bo[id[sx][sy]]=1;
    while(h<=t){
        int x=q[h++];bo[x]=0;
        for(int i=head[x];i;i=ed[i].next){
            int v=ed[i].v;
            if(dis[v]==dis[x]+ed[i].w){
                g[v]+=g[x];
                if(!bo[v]){bo[v]=1;q[++t]=v;}
            }
            if(dis[v]>dis[x]+ed[i].w){
                g[v]=g[x];
                dis[v]=dis[x]+ed[i].w;
                if(!bo[v]){bo[v]=1;q[++t]=v;}
            }
        }
    }
    if(dis[id[tx][ty]]==dis[0])printf("-1
");
    else printf("%d
%d
",dis[id[tx][ty]]-1,g[id[tx][ty]]);
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
            if(a[i][j]==3){sx=i;sy=j;a[i][j]=0;}
            if(a[i][j]==4){tx=i;ty=j;a[i][j]=0;}
        }
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)id[i][j]=++tot;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(a[i][j])continue;
            for(int k=0;k<8;k++){
                int x=i+dx[k],y=j+dy[k];
                if(jj(x,y)&&!a[i][j])add(id[i][j],id[x][y],1);
            }
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)if(a[i][j]==1&&(!bo[id[i][j]])){
            memset(vis,0,sizeof vis); cnt=0;
            dfs(i,j); bo[id[i][j]]=1;
            for(int k=1;k<=cnt;k++)
                for(int l=1;l<=cnt;l++)
                    if(!road[qq[k]][qq[l]]){
                        road[qq[k]][qq[l]]=1;road[qq[l]][qq[k]]=1;
                        add(qq[k],qq[l],1);add(qq[l],qq[k],1);
                    }
        }
    spfa();
    return 0;
}

考试真好。

原文地址:https://www.cnblogs.com/Ren-Ivan/p/7746667.html