100+100+10=210 rank 1
T1,醉了,考试时对拍平均1分钟一个错,真爽……暴力枚举约数判断就好了,从根dfs,当
#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;
}
考试真好。