「NOIP模拟赛」小奇的仓库
原题:「East!_XI」第一个问题 2015年10月4日hzwer改写了题面
「题目背景」
小奇采的矿实在太多了,它准备在喵星系建个矿石仓库。令它无语的是,喵星系的货运飞船引擎还停留在上元时代!
「问题描述」
喵星系有n个星球,星球以及星球间的航线形成一棵树。
从星球a到星球b要花费[dis(a,b) Xor M]秒。(dis(a,b)表示ab间的航线长度,Xor为位运算中的异或)
为了给仓库选址,小奇想知道,星球i(1<=i<=n)到其它所有星球花费的时间之和。
「输入格式」
第一行包含两个正整数n,M。
接下来n-1行,每行3个正整数a,b,c,表示a,b之间的航线长度为c。
「输出格式」
n行,每行一个整数,表示星球i到其它所有星球花费的时间之和。
「样例输入」
4 0
1 2 1
1 3 2
1 4 3
「样例输出」
6
8
10
12
「数据范围」
序号 N M
1 6 0
2 100 5
3 2000 9
4 50000 0
5 50000 0
6 50000 1
7 50000 6
8 100000 10
9 100000 13
10 100000 15
保证答案不超过2*10^9
题解
出题人18357:
算法1:
不会写函数的小伙伴们,我们只需要写个floyd,就有10分啦!
算法2:
在算法1的基础上,我们对每条边处理一下xor,就有20分啦!
算法3:
简单的树形DP,或者你会nlogn的dij,处理完每个点到其它点的最短路后再加上xor,那么这样就有30分啦!
算法4:
第4、5个点无需xor,那么我们树形DP扫一个节点与其它所有节点的路径长度之和,可以合并信息,最终均摊O(1),50分到手。
算法5:
第6个点xor 1,那么我们树形DP到一个点时记录有多少个0,多少个1,然后每当一条路径到2,那部分就再记录一个值,60分到手。
算法6:
如果你第6个点都过了,却没有满分,笨死啦!
一样的嘛,就是原来的“0”、“1”、大于等于2变成了0~16么~~
满了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
#include<set> #include<map> #include<ctime> #include<queue> #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define inf 1000000000 #define pa pair<int,int> #define ll long long #define mod 45989 using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int bin[20]; int n,m,cnt; int dis[100005],last[100005]; int f[100005][16],g[100005],t[16]; struct edge{ int to,next,v; }e[200005]; void insert(int u,int v,int w) { e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w; e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=w; } void dfs1(int x,int fa) { for(int i=last[x];i;i=e[i].next) if(e[i].to!=fa) { dfs1(e[i].to,x); g[x]+=g[e[i].to]+e[i].v/16; f[x][e[i].v%16]++; for(int j=0;j<16;j++) { int k=j+e[i].v; g[x]+=k/16*f[e[i].to][j]; f[x][k%16]+=f[e[i].to][j]; } } } void dfs2(int x,int fa) { for(int i=last[x];i;i=e[i].next) if(e[i].to!=fa) { int tmp=g[x]-g[e[i].to]; for(int j=0;j<16;j++) { int k=j+e[i].v; tmp-=k/16*f[e[i].to][j]; t[k%16]=f[x][k%16]-f[e[i].to][j]; } t[e[i].v%16]--; g[e[i].to]+=tmp; f[e[i].to][e[i].v%16]++; for(int j=0;j<16;j++) { int k=j+e[i].v; g[e[i].to]+=k/16*t[j]; f[e[i].to][k%16]+=t[j]; } dfs2(e[i].to,x); } } int main() { bin[0]=1; for(int i=1;i<20;i++)bin[i]=bin[i-1]<<1; n=read(),m=read(); for(int i=1;i<n;i++) { int u=read(),v=read(),w=read(); insert(u,v,w); } dfs1(1,0); dfs2(1,0); for(int i=1;i<=n;i++) { ll ans=g[i]*16; for(int j=0;j<16;j++)ans+=(j^m)*f[i][j]; printf("%I64d\n",ans); } return 0; } |
讲得很不错
%%%%244352345343452345
我太难了
我真是笨死了
ym
[捂脸熊]然后我过了前6个点,却没有AC,真是笨死了QAQ