zoukankan      html  css  js  c++  java
  • [国家集训队] 聪聪可可

    洛谷 P2634 传送门

    我们知道一共有n^2种取法,那么我们无需计算概率,只需统计有多少取法能满足mod 3=0就行了。

    那这道题就是经典的点分治套路了。

    把路径长mod 3之后,统计长为0,1,2的分别有多少。

    然后0和0可以合到一起,1和2可以合到一起。

    注意(1,2)和(2,1)算两种。

    最后分子分母同除gcd就行了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int n,ans;
     7 int hd[20005],to[40005],nx[40005],len[40005],ec;
     8 
     9 void edge(int af,int at,int el)
    10 {
    11     to[++ec]=at;
    12     len[ec]=el;
    13     nx[ec]=hd[af];
    14     hd[af]=ec;
    15 }
    16 
    17 int rt,tot;
    18 int del[20005];
    19 int sz[20005],mx[20005];
    20 int dis[20005],cnt[3];
    21 
    22 void weigh(int p,int fa)
    23 {
    24     sz[p]=1;mx[p]=0;
    25     for(int i=hd[p];i;i=nx[i])
    26     {
    27         int tar=to[i];
    28         if(tar==fa||del[tar])continue;
    29         weigh(tar,p);
    30         sz[p]+=sz[tar];
    31         mx[p]=max(mx[p],sz[tar]);
    32     }
    33     mx[p]=max(mx[p],tot-sz[p]);
    34     if(mx[p]<mx[rt])rt=p;
    35 }
    36 
    37 void dfs(int p,int fa)
    38 {
    39     cnt[dis[p]%3]++;
    40     for(int i=hd[p];i;i=nx[i])
    41     {
    42         int tar=to[i];
    43         if(tar==fa||del[tar])continue;
    44         dis[tar]=dis[p]+len[i];
    45         dfs(tar,p);
    46     }
    47 }
    48 
    49 int count(int p,int d0)
    50 {
    51     dis[p]=d0;
    52     cnt[0]=cnt[1]=cnt[2]=0;
    53     dfs(p,0);
    54     return cnt[0]*cnt[0]+cnt[1]*cnt[2]*2;
    55 }
    56 
    57 void conquer(int p)
    58 {
    59     del[p]=1;
    60     ans+=count(p,0);
    61     for(int i=hd[p];i;i=nx[i])
    62     {
    63         int tar=to[i];
    64         if(del[tar])continue;
    65         ans-=count(tar,len[i]);
    66         rt=0;tot=sz[tar];
    67         weigh(tar,0);
    68         conquer(rt);
    69     }
    70 }
    71 
    72 int gcd(int x,int y)
    73 {
    74     return y?gcd(y,x%y):x;
    75 }
    76 
    77 int main()
    78 {
    79     scanf("%d",&n);
    80     for(int i=1;i<n;i++)
    81     {
    82         int ff,tt,vv;
    83         scanf("%d%d%d",&ff,&tt,&vv);
    84         edge(ff,tt,vv%3);
    85         edge(tt,ff,vv%3);
    86     }
    87     mx[0]=tot=n;
    88     weigh(1,0);
    89     conquer(rt);
    90     tot=n*n;
    91     int g=gcd(ans,tot);
    92     ans/=g;tot/=g;
    93     printf("%d/%d",ans,tot);
    94     return 0;
    95 }
  • 相关阅读:
    linux 多进程并发服务__关于子进程回收的方法
    Qt中图元对象的多重集成
    Qmake: Q_OBJECT
    Qt Creator 启动失败 可能的解决办法
    Oracle 系统改变号SCN详解
    rman之创建恢复目录笔记
    Oracle 生成和显示执行计划的方法
    系统数据文件备份与恢复及只读数据文件备份与恢复
    没有备份、只有归档日志,如何恢复数据文件?
    ORACLE UNDO REDO查看
  • 原文地址:https://www.cnblogs.com/cervusy/p/9997045.html
Copyright © 2011-2022 走看看