题意:
Peter喜欢幸运数字。这里所说的幸运数字是由4和7组成的正整数。比如,数字47,744,4是幸运数字,而5,17,467就不是。
一天,Peter遇到一棵由n个点组成的树。另外,这棵树是带权的,即每条边有一个权值(由一个正整数表示)。如果一条边的权值是一个幸运数字,那么我们就说这条边是一条幸运边。说明一下,一棵n个结点的树是由n个结点和n-1条边组的无环的无向图。
Peter好奇,在树中有多少个满足以下条件的三元组tr(i,j,k)(i,j,k是三个不同的点)。
1.i到j有路径,i到k也有路径
2.每条路径中至少有一条幸运边。
数字的顺序是有意义的,举例说明,tr(1,2,3),tr(1,3,2),tr(2,1,3)是三个不同的序列。
现在要求计算在树中存在多少个这样的三元组关系。
题解
本题和51nod 1253 Kundu and Tree是基本一样的,只不过本题是有顺序
依旧容斥
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int maxn=1e5+10; int n,f[maxn],size[maxn]; void Init(); int Find(int); void Jion(int,int); LL GetThree(int); bool Judge(int); signed main(){ // freopen("in.cpp","r",stdin); Init(); return 0; } void Init(){ scanf("%d",&n); for(int i=1;i<=n;i++)f[i]=i,size[i]=1; int x,y,z; for(int i=1;i<n;i++){ scanf("%d%d%d",&x,&y,&z); if(!Judge(z))Jion(x,y); } LL ans=GetThree(n); for(int i=1;i<=n;i++){ if(Find(i)!=i)continue; ans-=GetThree(size[i]); ans-=2ll*size[i]*(size[i]-1)*(n-size[i]); } printf("%lld ",ans); } int Find(int x){ if(f[x]==x)return x; return f[x]=Find(f[x]); } void Jion(int x,int y){ int fx=Find(x),fy=Find(y); if(fx==fy)return; f[fx]=fy; size[fy]+=size[fx]; } LL GetThree(int x){ return 1ll*x*(x-1)*(x-2); } bool Judge(int x){ int tmp; while(x){ tmp=x%10; if(tmp!=4 && tmp!=7)return false; x/=10; } return true; }