zoukankan      html  css  js  c++  java
  • 2015上海网络赛 A Puzzled Elena

    题意:给定一棵树,求这个节点的所有子树中包括他本身与它互质的节点的个数.

    解题思路:题利用dfs序+容斥原理+前缀和性质解决。题目中要求每个结点,和多少个它的子结点互素。如果每次为了求一个点去跑一遍dfs,复杂度将是 O(N(N+M))。一定会超时。因此需要深入加以分析。注意到n的范围是10^5以内的,因此可以事先用线性筛求出每个数含有哪些素因子。接下来,我们 尝试利用dfs序来求解。设num[i]表示遍历到当前结点时候,含有因数i(注意,不一定是素数)的结点个数。可以发现,如果第一次遍历到结点u,含有 u的因数的个数为a,那么第二次遍历到u时候,含有u的因数的个数变成了b,那么b-a就是u的子树中,含有u的因数的结点个数,即和u不互素的结点个 数。用总的结点数减掉这部分,即得到了和u互素的结点个数。这正是用了前缀和的性质。那么,如何求解有当前有多个结点含有u的因数呢?可以利用容斥原理求解。因为我们已经预处理出来了所有数的素因数,假设有len个素因数,由于“含 有”即表示只要有1个即可。因此结果就是{只含有1种素因子的个数}-{只含有2种素因子的个数}+{只含有3个素因子的个数}-...+ (-1)^(n-1){含有n个素因子的个数}。这恰好就是容斥原理。至此,问题得以解决。

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<iostream>
      6 #include<memory.h>
      7 #include<cstdlib>
      8 #include<vector>
      9 #define clc(a,b) memset(a,b,sizeof(a))
     10 #define LL long long int
     11 using namespace std;
     12 const int N=100010;
     13 const double eps=1e-8;
     14 const int inf=0x3f3f3f3f;
     15 
     16 int n;
     17 int val[N];
     18 int ans[N];
     19 int e;
     20 int num[N];
     21 int head[N];
     22 vector<int>g[N];
     23 struct Edge
     24 {
     25     int to,next;
     26 }edge[N*2];
     27 
     28 void add(int u,int v)
     29 {
     30    edge[e].to=v;
     31    edge[e].next=head[u];
     32    head[u]=e++;
     33 }
     34 
     35 void init()
     36 {
     37     for(int i=2;i<N;i++)
     38     {
     39         if(!g[i].empty())
     40             continue;
     41         for(int j=i;j<N;j+=i)
     42             g[j].push_back(i);
     43     }
     44 }
     45 
     46 int calc(int x,int y)//*y=0表示进入这颗树的时候,含有互质的数目为0;y=1表示dfs回溯的时候离开这棵树相应互质节点数目加一*//
     47 {
     48     int len=g[x].size();
     49     int res=0;
     50     for(int i=1;i<(1<<len);i++)
     51     {
     52         int t=1;
     53         int cnt=0;
     54         for(int j=0;j<len;j++)
     55         {
     56             if(i&(1<<j))
     57             {
     58                 cnt++;
     59                 t=t*g[x][j];
     60             }
     61         }
     62         if(cnt%2)
     63             res+=num[t];
     64         else
     65             res-=num[t];
     66         num[t]+=y;
     67     }
     68     return res;
     69 }
     70 int dfs(int u,int pre)
     71 {
     72     int cnt=0;
     73     int L=calc(val[u],0);
     74     for(int i=head[u];~i;i=edge[i].next)
     75     {
     76         int v=edge[i].to;
     77         if(v==pre)
     78             continue;
     79         cnt+=dfs(v,u);
     80     }
     81     int R=calc(val[u],1);
     82     ans[u]=cnt-(R-L);
     83     if(val[u]==1)
     84     ans[u]++;
     85     return cnt+1;
     86 }
     87 int main()
     88 {
     89     int u,v;
     90     int cas=1;
     91     while(~scanf("%d",&n))
     92     {
     93         e=0;
     94         init();
     95         clc(num,0);
     96         clc(head,-1);
     97         for(int i=0;i<n-1;i++)
     98         {
     99             scanf("%d%d",&u,&v);
    100             add(u,v);
    101             add(v,u);
    102         }
    103         for(int i=1;i<=n;i++)
    104         {
    105             scanf("%d",&val[i]);
    106         }
    107         dfs(1,0);
    108         printf("Case #%d:",cas++);
    109         for(int i=1;i<=n;i++)
    110         {
    111            printf(" %d",ans[i]);
    112         }
    113         printf("
    ");
    114     }
    115     return 0;
    116 }
    View Code
  • 相关阅读:
    SGU438_The Glorious Karlutka River =)
    SGU326_Perspective
    Problem B. Harvest of Apples(莫队+数学)
    【HDU2019多校】1005
    【HDU2019多校】K
    L
    「2017 山东一轮集训 Day2」Pair (霍尔定理+线段树)
    【2017西安】Sum of xor sum(线段树)
    【2017西安】 XOR (线性基+思维)
    【SPOJ】Lightning Conductor (dp+决策单调性)
  • 原文地址:https://www.cnblogs.com/ITUPC/p/4867364.html
Copyright © 2011-2022 走看看