• 不平凡的许愿树


    【题目描述】

    noip要到了,大家来到许愿树前。这个许愿树不仅仅是许愿树,还有未卜先知的功能。众OIer问许愿树:“不平凡的许愿树,CCF告诉我们noip中会有两道题目从Openjudge上选择,你能不能告诉我是哪两道题。”

    许愿树想了想直接说出答案并不妥:“中国有句古话叫‘闷声大发财’,我就什么也不说,这是最好的。但是我看到你们这么热情,一句话不说也不好,我就告诉你们点信息吧。你们看我是一个由N个结点组成的树,在树中任选着3个点,有多少种选择方案使得这三个点互相之间的距离相同?两个方案不同当且仅当一个点在第一种方案中被选择,第二种方案中没有被选择。”

    “记你算出来方案数为cnt,那么第一道题的题号就是cnt%338 + 1,第二题的题目编号是(cnt+233)%338+1。”

    可是OIer们手头并没有计算机,于是请你来告诉他们题目编号。

    【输入格式】

    第一行一个整数N,表示树有N个点。

    接下来N-1行,每行两个整数u,v,表示树中有一条从u到v的边

    【输出格式】

    一行,两个整数,分别为预测的第一题题号和第二题题号。

    【样例输入】

    7
    1 2
    5 7
    2 5
    2 3
    5 6
    4 5

    【样例输出】

    6 239

    【提示】

    样例解释:

    共有5种方案,分别是{1,3,5},{2,4,6},{2,4,7},{2,6,7},{4,6,7}。所以第一题的编号为5%338 + 1 = 6;第二题的编号为(5+233)%338 + 1 = 239;

    数据范围与约定:

    对于30%的数据:1 <= n <= 100

    对于60%的数据:1 <= n <= 1500

    对于100%的数据:1 <= n <= 5000

    题解:

    显然不知道怎么dp 就乱搞,又显然以每个点dfs然后组合O(n^2)但看到样例就知道重复统计了

    所以我强制规定三元点对必须分布在三颗不同子树上,就不会重复了...............................................

    然后就来了个(n*log3n)≈(n^2)的玄学方法 结果跑得还挺快

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cmath>
     6 using namespace std;
     7 const int N=5005,mod=338;
     8 int n,head[N],num=0,du[N];
     9 struct Lin{
    10     int next,to;
    11 }a[N<<1];
    12 void init(int x,int y){
    13     a[++num].next=head[x];
    14     a[num].to=y;
    15     head[x]=num;
    16 }
    17 int t[N],c[N][N],sz[N];
    18 void dfs(int x,int last,int dep,int rt){
    19     int u;
    20     t[dep]++;
    21     for(int i=head[x];i;i=a[i].next){
    22         u=a[i].to;
    23         if(u==last || u==rt)continue;
    24         dfs(u,x,dep+1,rt);
    25     }
    26 }
    27 int ans=0,sum[N];
    28 void solve(){
    29     for(int i=1;i<=n;i++){
    30         if(!sz[i])break;
    31         for(int j=1;j<=sz[i];j++)sum[j]=sum[j-1]+c[i][j];
    32         for(int j=1;j<sz[i]-1;j++){
    33             for(int k=j+1;k<sz[i];k++){
    34                 ans+=(sum[sz[i]]-sum[k])*c[i][j]*c[i][k];
    35                 ans%=mod;
    36             }
    37         }
    38         sz[i]=0;
    39     }
    40 }
    41 int main()
    42 {
    43     freopen("hopetree.in","r",stdin);
    44     freopen("hopetree.out","w",stdout);
    45     scanf("%d",&n);
    46     int x,y;
    47     for(int i=1;i<n;i++){
    48         scanf("%d%d",&x,&y);
    49         init(x,y);init(y,x);
    50         du[x]++;du[y]++;
    51     }
    52     for(int i=1;i<=n;i++)
    53     {
    54         if(du[i]<3)continue;
    55         for(int j=head[i];j;j=a[j].next){
    56             dfs(a[j].to,a[j].to,1,i);
    57             for(int k=1;k<=n;k++){
    58                 if(!t[k])break;
    59                 c[k][++sz[k]]=t[k];
    60                 t[k]=0;
    61             }
    62         }
    63         solve();
    64     }
    65     printf("%d %d
    ",ans+1,((ans+233)%mod)+1);
    66 }
  • 相关阅读:
    为什么不应该使用ZooKeeper做服务发现
    Python 练习 人事管理
    Python 爬取 妹子图(技术是无罪的)
    Python 爬取 书籍
    Python 爬取 豆瓣
    Python 爬取 房天下
    Python 爬取 煎蛋
    Python 爬取 拉钩
    Python 爬取 猫眼
    家具专区网
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7192664.html
Copyright © 2020-2023  润新知