博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
牛客練習賽32 B-Xor-Path 技巧題
阅读量:6428 次
发布时间:2019-06-23

本文共 1370 字,大约阅读时间需要 4 分钟。

原題:

  題目大意:

  給定一棵樹,求樹上所有點對之間路徑上的值的異或和,即對所有點對( i , j )n >= i >= 1,n >= j >= 1且i != j,這些所有的點對間路徑上的值的異或和,的異或和

  解題大意:

  根據Xor的性質,同一個數抑或偶數次為0,奇數次為它本身,所以只要知道一個節點值被Xor的次數,就知道它對答案有沒有貢獻,最後把那些被Xor奇數次的值,即Xor後不為0的值,求它們的Xor和就是答案。

  這裡DFS一遍,就可以算出每個節點被Xor多少次。一個節點被Xor的次數分成兩部分,從它出發到其他(n-1)個節點的路徑數,和經過它的路徑數。算經過它的路徑時,就有點技巧:

  怎樣不重不漏地算出這些節點經過它的兩兩之間的路徑數。對於一個結點,搜它的子樹,記已經搜到的節點數為sum,每次搜一個枝,得到temp個點,temp*sum,就是這temp個節點與sum個節點間經過本節點的路徑數,然後把temp加到sum裡面去,繼續搜下一個枝,進行同樣的操作即可,然後再考慮子樹節點與非子樹節點間的路徑。仔細思考就能發現這就不重不漏了。之前想到複雜度很高的方法,TLE了

AC代碼:

#include
using namespace std;typedef long long ll;const int mod = 1e9+7;const int N = 1e6;int n,m,cnt;int head[N];int val[N];bool f[N];struct Edge{ int to,next;}e[N];void add(int u,int v){ e[cnt].to=v; e[cnt].next=head[u]; head[u]=cnt++;}int dfs(int now,int fa){ int sum=0; long long t=0; int temp; for(int i=head[now];i!=-1;i=e[i].next) { if(e[i].to!=fa) { temp=dfs(e[i].to,now); //每次搜索上來 t+=(temp*sum)%2; //與之前搜到的和相乘,即可,只判斷奇偶,%2即可 sum+=temp; } } t=(t+n-1)%2; //從本節點出發的路徑 t+=((n-sum-1)*sum)%2; //所有從子樹節點出發,到非子樹節點的路徑 if(t%2) f[now]=1; return sum+1;}int main(){ memset(f,0,sizeof(f)); memset(head,-1,sizeof(head)); scanf("%d",&n); int u,v; for(int i=1;i

 

转载于:https://www.cnblogs.com/Lin88/p/10073267.html

你可能感兴趣的文章
BGP最新的AS号:4-byte-as 转换为十进制及AS号兼容性
查看>>
Windows2008server R2 组策略批量更改本地管理员密码
查看>>
ubutnu安装geany
查看>>
webservice 之 Java CXF实战效果 RS WS(一)
查看>>
我的友情链接
查看>>
Repository 与 DAO
查看>>
Zabbix监控Windows主机
查看>>
IBM x3850 RAID5数据恢复方案及过程
查看>>
移动计算领域五大机遇:交通运输优势待挖掘
查看>>
如何把win7 旗舰版升级到sp1最新版本
查看>>
Software Enginering-------using git
查看>>
浅谈IP地址-1
查看>>
我的友情链接
查看>>
C#中的线程池使用(一)
查看>>
利用Windows Server Backup功能备份活动目录
查看>>
RAC维护手记08-ASM磁盘组信息查看常用命令
查看>>
实验08 磁盘和文件系统管理
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
FastDFS整合nginx后,nginx一直报错
查看>>