AtCoder汇总

AGC024(5.20) (rank 795 rating 240)

总结:猜结论,“可行即最优”

A:  给定A,B,C,每次每个数变成另外两个数的和,求k次后B-A的值。

观察发现就是B-A,A-B依次出现,根据k的奇偶性输出即可。

B: 给定一个n的排列,每次可以将一个数移到开头或结尾,求变成1,2,...,n所需的最小步数。

找到一个最长的i,i+1,...,j满足在排列中的位置递增,这些数可以保留,答案就是n-(j-i+1)。

C: 给定一个数列A,初始数列X全为0,每次可以让X[i+1]=X[i]+1,求最少多少次能变成A。

首先特判掉A[1]>0和A[i+1]>A[i]+1的情况,然后如果A[i+1]=A[i]+1,那么只需要ans++,否则ans+=A[i+1]。

D: 给你一棵无根树,你可以在树中任意新增点,然后将树染色,满足以同一颜色的任意两个点为根的两棵树同构,问最少要多少种颜色,且在颜色数最少的情况下,这棵树最少有多少个度数为1的点。

找到一个点使以这个点为根的树深度最小(这个深度同时也是$\lceil \frac{D}{2} \rceil$,D为树的直径长)。

如果使得深度最小的点有两个,那么显然要让这棵树关于这两个点轴对称。如果有一个,可以使整棵树关于这个点中心对称,也可以任选一个和这个点相邻的点,让这棵树关于这两个点轴对称。两种方案讨论一下即可。

扫描二维码关注公众号,回复: 964801 查看本文章
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=l; i<=r; i++)
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=210;
 9 int n,u,v,mn,p,cnt,tot,h[N],a[N],d[N],to[N],nxt[N],b[N],dep[N][N];
10 
11 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
12 
13 void dfs(int x,int fa,int k){
14     dep[k][x]=dep[k][fa]+1;
15     for (int i=h[x],v; i; i=nxt[i])
16         if ((v=to[i])!=fa) dfs(v,x,k);
17 }
18 
19 ll work(int x,int y){
20     ll res=1;
21     memset(b,0,sizeof(b));
22     rep(i,1,n){
23             int p=min(dep[x][i],dep[y][i]);
24             b[p]=max(b[p],d[i]-1);
25     }
26     rep(i,1,n) if (b[i]) res*=b[i]; else break;
27     return res<<1;
28 }
29 
30 ll work1(int x){
31     ll res=1;
32     memset(b,0,sizeof(b));
33     rep(i,1,n) b[dep[x][i]]=max(b[dep[x][i]],d[i]-1);
34     rep(i,2,n) if (b[i]) res*=b[i]; else break;
35     return res*d[x];
36 }
37 
38 int main(){
39     freopen("d.in","r",stdin);
40     freopen("d.out","w",stdout);
41     scanf("%d",&n); mn=n+1;
42     rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u),d[u]++,d[v]++;
43     rep(i,1,n) dfs(i,0,i);
44     rep(i,1,n) rep(j,1,n) dep[i][0]=max(dep[i][0],dep[i][j]);
45     rep(i,1,n) mn=min(mn,dep[i][0]);
46     rep(i,1,n) if (dep[i][0]==mn) a[++tot]=i;
47     if (tot==2) printf("%d %lld\n",mn-1,work(a[1],a[2]));
48     else{
49         ll ans=work1(a[1]);
50         for (int i=h[a[1]]; i; i=nxt[i]) a[++tot]=to[i];
51         rep(i,2,tot) ans=min(ans,work(a[1],a[i]));
52         printf("%d %lld\n",mn,ans);
53     }
54     return 0;
55 }
D

猜你喜欢

转载自www.cnblogs.com/HocRiser/p/9066002.html