2014 Multi-University Training Contest 1
官方解题报告http://blog.sina.com.cn/s/blog_a19ad7a10102uyes.html
B. Jump
最小K路径覆盖的模型,用费用流或者KM算法解决,构造二部图,X部有N*M个节点,源点向X部每个节点连一条边,流量1,费用0,Y部有N*M个节点,每个节点向汇点连一条边,流量1,费用0,如果X部的节点x可以在一步之内到达Y部的节点y,那么就连边x->y,费用为从x格子到y格子的花费能量减去得到的能量,流量1,再在X部增加一个新的节点,表示可以从任意节点出发K次,源点向其连边,费用0,流量K,这个点向Y部每个点连边,费用0,流量1,最这个图跑最小费用最大流,如果满流就是存在解,反之不存在,最小费用的相反数就是可以获得的最大能量
C. Centroid of a Tree
首先找出重心,之后以重心为根进行树形dp,用dp[i][j]表示以编号为i的节点为根的子树有j个儿子的方案数 ,这个直接合并,每次合并两个子树的时候枚举两个子树的儿子的个数,对于树上每条边合并一次,总共合并n 次,每次合并的复杂度是n^2,这个是三方的复杂度。
对于有两个重心的情况,首先将这两个子树中间的边打断变成两个树,对这两个树分别按照上述方法处理出dp 数组,如果要使得重心位置不变,那么这两个子树需要有相同的节点个数,这个直接枚举一下然后两边乘起来 就好了。
至于只有一个重心的情况,还是按照上述方法处理出dp数组,为了计算合法的方案数,我们用总的方案数减去 不合法的方案数,对于不合法的情况,去掉这个根后一定会有一个最大的分支,这个分支的节点数超过剩下的 全部分支加起来的节点个数,所以先枚举最大分支,对于剩下的分支用背包处理,f[i]表示剩下的全部子树取i 个节点的方案数,这个很容易处理,处理完之后枚举一下最大分支的节点个数,再利用f数组就可以算出在这种 情况下的非法的方案数了。
对于这里的复杂度要特别说明一下,设每个分支的节点数是x1,x2,x3...,xk,合并的复杂度是x1*x2+(x1+x2) *x3+...+(x1+x2+...+xk-1)*xk<=(x1+x2+...+xk)^2=n^2,加上枚举是三方,所以整个dp的总复杂度是三方的。
D. Task
基本思想是贪心。
对于价值c=500*xi+2*yi,yi最大影响100*2<500,所以就是求xi总和最大。可以先对机器和任务的时间从大到小排序。从最大时间的任务开始,找出满足任务时间要求的所有机器,从中找出等级最低且满足任务等级要求的机器匹配。依次对任务寻找满足要求的机器。
F. Shooting
将所有目标与起点线的距离离散化作为下标,建立函数式线段树,将距离按区间端点从1到X的顺序加入函数式线段树,左端点+1,右端点-1,记录区间元素的距离和,以及元素的个数。对于在x位置的询问,找到其对应的端点,这个可以二分找到,然后在该端点对应的线段树上进行二分查找求解,最后判断前一个答案与P的大小得到当前问题的答案。
G. Xor
线段树,时间复杂度是O(5000*200*logn+10*m*logn)。
f[ prefix ]保存2进制前缀状态,合并就暴力,比如
101xxx
11xxxx
x表示0或者1
前缀固定 后面随便取
这2个xor的结果
只有前2位是确定的
合并完大约就是
01xxxx
然后方案数就可以算了,可以证明,状态不会太多。
H. Information Extraction
本题要求大家能够存储特定的输出格式以及若干种HTML结构和映射关系,根据输入的HTML文本,寻找其结构,如果找不到结构与之匹配,输出“Can't Identify”,如果只有一个,根据映射关系以及输出格式的要求输出结果,如果有多个,则使用最早输入的那个结构。
解决以下几点即可
1、对HTML输入的读取
2、判断结构是不是输入的HTML文本的结构
3、根据映射以及输出格式的要求输出结果
注意映射关系中可能有一个id到多个标签,并且这些标签在输入格式中是存在多个的。
I. Turn the pokers
最终的结果一定是连续出现的,只需要求出最终的区间。
因为如果对同一张牌进行两次操作,牌的状态不改变。故牌的翻转次数一定是减少偶数次。如果所有数的和是奇数,那么最终结果也一定是奇数。同理,偶数也是一样的。
所以只要递推求出最后的区间,计算sum(C(xi,m)(i=0,1,2。。。)),m是总牌数,xi是在区间内连续的奇数或偶数,在模10^9+9就是最终的答案。
J. Rating
令(x, y)表示高分为x,低分为y的状态(x >= y),E(x, y)表示从(x, y)到达(1000, ?)的比赛场数期望。容易得到E(x, y) = P * E(x1, y1) + (1 - P) * E(x2, y2) + 1,其中,(x1, y1)表示rating上升后的状态,(x2, y2)表示rating下降后的状态。把E(1000, ?) = 0带入可以得到包含n个未知数的n个方程,n大概200多,可以高斯消元。E(0, 0)即为答案。
K. Shortest-path tree
首先构造最短路径树。先求根节点到其他节点的最短路径,然后从根节点开始进行深度优先遍历,先遍历节点编号较小的没遍历过的儿子,这样就能处理处最短路径树。
之后找节点数为K的树链。可以用树分治进行求解,在树分治求解过程中,对于每个中心点,处理出该子树中所有节点到中心点的树链,然后枚举每条树链,比如某条树链节点为a,长度为b,则找之前遍历过的树链中节点数位K-a的长度最长的树链,将这两条树链拼起来可以得到节点数为K的树链,用其更新答案。最好一个一个分支分别处理,可以避免考虑同一个分支来的两条树链。这样枚举并且更新信息,还要存方案数。
Couple doubi http://acm.hdu.edu.cn/showproblem.php?pid=4861
找规律。
1 #include<cstdio> 2 using namespace std; 3 int main(){ 4 int n,p; 5 while(~scanf("%d%d",&n,&p)){ 6 if(n/(p-1)&1)puts("YES"); 7 else puts("NO"); 8 } 9 return 0; 10 }
Jump http://acm.hdu.edu.cn/showproblem.php?pid=4862
最小费用最大流。id[][]给每个点标号表示左侧,id[][]+cnt表示右侧点,源点s连每一个左侧点,每一个右侧点连到汇点en。流量都是1,费用都是0。在一个中间点ps,源点s到他k的流,ps到每一个右侧点1的流,因为走k次,这里也就相当于这个点不经过其他点,直接流向en,但只有k个起点。题目要求赚最大能量,把能量取个相反数,当做费用,这样求的最小费用的绝对值就是最大能量了。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #define mt(a,b) memset(a,b,sizeof(a)) 5 using namespace std; 6 const int M=1010; 7 const int inf = 0x3f3f3f3f; 8 class MaxflowMincost { //最小费用最大流 9 struct E { 10 int u,v,next,flow,cost; 11 } e[M<<4]; 12 queue<int> q; 13 int le,flow,cost,head[M],cur[M],dis[M],pre[M]; 14 bool used[M],sign[M]; 15 public: 16 int getcost() { 17 return cost; 18 } 19 int getflow() { 20 return flow; 21 } 22 bool spfa(int s,int t) { 23 mt(used,0); 24 mt(sign,0); 25 mt(dis,0); 26 while(!q.empty()) q.pop(); 27 q.push(s); 28 used[s]=sign[s]=true; 29 while(!q.empty()) { 30 int u=q.front(); 31 q.pop(); 32 used[u]=false; 33 for(int i=head[u]; ~i; i=e[i].next) { 34 if(e[i].flow<1) continue; 35 int v=e[i].v; 36 if(!sign[v]||dis[v]>dis[u]+e[i].cost) { 37 dis[v]=dis[u]+e[i].cost; 38 sign[v]=true; 39 pre[v]=u; 40 cur[v]=i; 41 if(used[v]) continue; 42 used[v]=true; 43 q.push(v); 44 } 45 } 46 } 47 return sign[t]; 48 } 49 void init() { 50 le=0; 51 mt(head,-1); 52 } 53 void add(int u,int v,int flow,int cost) { 54 e[le].u=u; 55 e[le].v=v; 56 e[le].flow=flow; 57 e[le].cost=cost; 58 e[le].next=head[u]; 59 head[u]=le++; 60 e[le].u=v; 61 e[le].v=u; 62 e[le].flow=0; 63 e[le].cost=-cost; 64 e[le].next=head[v]; 65 head[v]=le++; 66 } 67 void solve(int s,int t) { 68 flow=cost=0; 69 while(spfa(s,t)) { 70 int temp=t; 71 int now=inf; 72 while(temp!=s) { 73 now=min(now,e[cur[temp]].flow); 74 temp=pre[temp]; 75 } 76 flow+=now; 77 temp=t; 78 while(temp!=s) { 79 cost+=now*e[cur[temp]].cost; 80 e[cur[temp]].flow-=now; 81 e[cur[temp]^1].flow+=now; 82 temp=pre[temp]; 83 } 84 } 85 } 86 } gx; 87 char str[16][16]; 88 int id[16][16]; 89 int main() { 90 int T,n,m,k; 91 while(~scanf("%d",&T)) { 92 int cas=1; 93 while(T--) { 94 scanf("%d%d%d",&n,&m,&k); 95 for(int i = 0; i < n; i++) 96 scanf("%s",str[i]); 97 printf("Case %d : ",cas++); 98 gx.init(); 99 int cnt=0; 100 for(int i=0;i<n;i++){ 101 for(int j=0;j<m;j++){ 102 id[i][j]=cnt++; 103 } 104 } 105 int st=cnt++; 106 int ps=cnt++; 107 int en=cnt++; 108 gx.add(st,ps,k,0); 109 for(int i = 0; i < n; i++){ 110 for(int j = 0,w; j < m; j++) { 111 gx.add(st,id[i][j],1,0); 112 gx.add(id[i][j]+cnt,en,1,0); 113 gx.add(ps,id[i][j]+cnt,1,0); 114 for(int y = j+1; y < m; y++) { 115 w=y-j-1; 116 if(str[i][y] == str[i][j]) 117 w-=str[i][j]-'0'; 118 gx.add(id[i][j],id[i][y]+cnt,1,w); 119 } 120 for(int x = i+1; x < n; x++) { 121 w=x-i-1; 122 if(str[x][j] == str[i][j]) 123 w-=str[i][j]-'0'; 124 gx.add(id[i][j],id[x][j]+cnt,1,w); 125 } 126 } 127 } 128 gx.solve(st,en); 129 int flow=gx.getflow(); 130 int cost=gx.getcost(); 131 if(flow != n*m)printf("-1\n"); 132 else printf("%d\n",-cost); 133 } 134 } 135 return 0; 136 }
Centroid of a Tree http://acm.hdu.edu.cn/showproblem.php?pid=4863
dfs是树形dp找重心,然后看看有几个重心,不是一个就是两个,分两种情况讨论,如果是两个重心,将重心之间的边断开,两边分别DFS处理出dp[i][j]表示i号节点为根的子树有j个儿子的方案数。这里还没全懂。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<algorithm> 5 #define mt(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 const int M=512; 8 const int mod=10007; 9 struct G { 10 struct E { 11 int u,v,next; 12 bool flag; 13 } e[M*M]; 14 int le,head[M]; 15 void init() { 16 le=0; 17 mt(head,-1); 18 } 19 void add(int u,int v) { 20 e[le].u=u; 21 e[le].v=v; 22 e[le].flag=true; 23 e[le].next=head[u]; 24 head[u]=le++; 25 } 26 } g; 27 int n,num[M],big[M]; 28 void dfs(int u,int fa) { //find center 29 num[u]=1; 30 big[u]=0; 31 for(int i=g.head[u]; ~i; i=g.e[i].next) { 32 int v=g.e[i].v; 33 if(v!=fa) { 34 dfs(v,u); 35 num[u]+=num[v]; 36 big[u]=max(big[u],num[v]); 37 } 38 } 39 big[u]=max(big[u],n-num[u]); 40 } 41 struct S{ 42 int id,val; 43 friend bool operator <(S a,S b){ 44 return a.val<b.val; 45 } 46 }b[M]; 47 int dp[M][M];//dp[i][j]表示以编号为i的节点为根的子树有j个儿子的方案数 48 int save[M]; 49 void DFS(int u,int fa) { 50 for(int i=0; i<=n; i++) dp[u][i]=0; 51 dp[u][0]=1; 52 int T=0; 53 for(int i=g.head[u]; ~i; i=g.e[i].next) { 54 if(g.e[i].flag) { 55 int v=g.e[i].v; 56 if(v!=fa) { 57 DFS(v,u); 58 for(int j=0; j<=n; j++) save[j]=0; 59 for(int a=0; a<=T; a++) 60 for(int b=0; b<=num[v]; b++) { 61 int add=(dp[u][a]*dp[v][b])%mod; 62 save[a+b]=(save[a+b]+add)%mod; 63 } 64 for(int a=0; a<=n; a++) 65 dp[u][a]=save[a]; 66 T+=num[v]; 67 } 68 } 69 } 70 for(int i=n; i>=0; i--) 71 dp[u][i+1]=dp[u][i]; 72 dp[u][0]=1; 73 } 74 int f[2][M]; 75 int main() { 76 int t,x,y; 77 while(~scanf("%d",&t)) { 78 int cas=1; 79 while(t--) { 80 scanf("%d",&n); 81 g.init(); 82 for(int i=0;i<n-1;i++) { 83 scanf("%d%d",&x,&y); 84 g.add(x,y); 85 g.add(y,x); 86 } 87 printf("Case %d: ",cas++); 88 dfs(1,-1); 89 int lb=0; 90 for(int i=1;i<=n;i++){ 91 b[lb].id=i; 92 b[lb].val=big[i]; 93 lb++; 94 } 95 sort(b,b+lb); 96 if((lb>1&&b[0].val<b[1].val)||lb==1){ //一个重心 97 int rt=b[0].id; 98 dfs(rt,-1); 99 DFS(rt,-1); 100 int ans=1; 101 for(int i=g.head[rt]; ~i; i=g.e[i].next) { 102 int v=g.e[i].v; 103 int T=0; 104 for(int j=0; j<=n; j++) 105 T=(T+dp[v][j])%mod; 106 ans=(ans*T)%mod; 107 } 108 for(int i=g.head[rt]; ~i; i=g.e[i].next) { 109 int x=g.e[i].v; 110 int T=0; 111 int now=0; 112 int pre=1; 113 memset(f,0,sizeof(f)); 114 f[now][0]=1; 115 for(int j=g.head[rt];~j;j=g.e[j].next){ 116 if(i == j) continue; 117 int y=g.e[j].v; 118 now^=1; 119 pre^=1; 120 for(int a=0; a<=n; a++) 121 f[now][a]=0; 122 for(int a=0; a<=T; a++) 123 for(int b=0; b<=num[y]; b++) { 124 f[now][a+b]+=f[pre][a]*dp[y][b]; 125 f[now][a+b]%=mod; 126 } 127 T+=num[y]; 128 } 129 int sum=0; 130 for(int j=1; j<=n; j++) { 131 sum=(sum+f[now][j-1])%mod; 132 int add=(dp[x][j]*sum)%mod; 133 ans=(ans-add+mod)%mod; 134 } 135 } 136 printf("%d\n",ans); 137 } else { //two center 138 int x=b[0].id; 139 int y=b[1].id; 140 for(int i=0;i<g.le;i++){ 141 if((g.e[i].u==x&&g.e[i].v==y)||(g.e[i].u==y&&g.e[i].v==x)){ 142 g.e[i].flag=false; 143 g.e[i^1].flag=false; 144 break; 145 } 146 } 147 DFS(x,-1); 148 DFS(y,-1); 149 int ans=0; 150 for(int i=1; i<=n; i++) { 151 int add=(dp[x][i]*dp[y][i])%mod; 152 ans=(ans+add)%mod; 153 } 154 printf("%d\n",ans); 155 } 156 } 157 } 158 return 0; 159 }
Task http://acm.hdu.edu.cn/showproblem.php?pid=4864
二级排序,然后对x单调队列,y标记然后暴力找最接近的一个。y是100,所以复杂度o(m*100)。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cmath> 5 #include<cctype> 6 #include<iostream> 7 #include<algorithm> 8 #include<queue> 9 #define mt(a,b) memset(a,b,sizeof(a)) 10 using namespace std; 11 typedef __int64 LL; 12 const int M=100010; 13 struct NODE{ 14 int x,y; 15 friend bool operator <(NODE a,NODE b){ 16 if(a.x==b.x) return a.y>b.y; 17 return a.x>b.x; 18 } 19 }mach[M],task[M]; 20 int ma[128]; 21 int main(){ 22 int n,m; 23 while(~scanf("%d%d",&n,&m)){ 24 mt(ma,0); 25 for(int i=0;i<n;i++){ 26 scanf("%d%d",&mach[i].x,&mach[i].y); 27 } 28 for(int i=0;i<m;i++){ 29 scanf("%d%d",&task[i].x,&task[i].y); 30 } 31 sort(mach,mach+n); 32 sort(task,task+m); 33 int ans=0; 34 LL sum=0; 35 int id=0; 36 for(int i=0;i<m;i++){ 37 while(mach[id].x>=task[i].x&&id<n){ 38 ma[mach[id].y]++; 39 id++; 40 } 41 for(int j=task[i].y;j<=100;j++){ 42 if(ma[j]){ 43 ma[j]--; 44 ans++; 45 sum+=500*task[i].x+2*task[i].y; 46 break; 47 } 48 } 49 } 50 printf("%d %I64d\n",ans,sum); 51 } 52 return 0; 53 }
Peter's Hobby http://acm.hdu.edu.cn/showproblem.php?pid=4865
dp求一个概率最大的序列,记录路径,类似上海邀请赛c。
1 #include<cstdio> 2 #include<cstring> 3 #define mt(a,b) memset(a,b,sizeof(a)) 4 const int M=64; 5 char yezi[4][8]={"Dry","Dryish","Damp","Soggy"}; 6 char tian[3][8]={"Sunny","Cloudy","Rainy"}; 7 int a[M]; 8 char op[8]; 9 double dp[M][3]; 10 int pre[M][3]; 11 int ans[M]; 12 double f[3][4]={ 13 0.60,0.20,0.15,0.05, 14 0.25,0.30,0.20,0.25, 15 0.05,0.10,0.35,0.50, 16 }; 17 double s[3][3]={ 18 0.500,0.375,0.125, 19 0.250,0.125,0.625, 20 0.250,0.375,0.375, 21 }; 22 int main(){ 23 int t,n; 24 while(~scanf("%d",&t)){ 25 int cas=1; 26 while(t--){ 27 scanf("%d",&n); 28 for(int i=1;i<=n;i++){ 29 scanf("%s",op); 30 for(int j=0;j<4;j++){ 31 if(!strcmp(op,yezi[j])){ 32 a[i]=j; 33 break; 34 } 35 } 36 } 37 mt(dp,0); 38 mt(pre,-1); 39 dp[1][0]=0.63*f[0][a[1]]; 40 dp[1][1]=0.17*f[1][a[1]]; 41 dp[1][2]=0.20*f[2][a[1]]; 42 for(int i=2;i<=n;i++){ 43 for(int j=0;j<3;j++){ 44 for(int k=0;k<3;k++){ 45 if(dp[i][j]<dp[i-1][k]*s[k][j]*f[j][a[i]]){ 46 dp[i][j]=dp[i-1][k]*s[k][j]*f[j][a[i]]; 47 pre[i][j]=k; 48 } 49 } 50 } 51 } 52 double big=0; 53 int id; 54 for(int i=0;i<3;i++){ 55 if(big<dp[n][i]){ 56 big=dp[n][i]; 57 id=i; 58 } 59 } 60 int la=0; 61 int x=n; 62 ans[la++]=id; 63 while(pre[x][id]!=-1){ 64 id=pre[x][id]; 65 ans[la++]=id; 66 x--; 67 } 68 printf("Case #%d:\n",cas++); 69 for(int i=la-1;i>=0;i--){ 70 puts(tian[ans[i]]); 71 } 72 } 73 } 74 return 0; 75 }
Shooting http://acm.hdu.edu.cn/showproblem.php?pid=4866
主席树,待补。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int MAXN = 200010; 5 const int M = MAXN * 100; 6 int n,tot; 7 int T[MAXN]; 8 int lson[M],rson[M]; 9 int c1[M]; 10 long long c2[M]; 11 int build(int l,int r) { 12 int root = tot++; 13 c1[root] = 0; 14 c2[root] = 0; 15 if(l != r) { 16 int mid = (l+r)/2; 17 lson[root] = build(l,mid); 18 rson[root] = build(mid+1,r); 19 } 20 return root; 21 } 22 int update(int root,int pos,int val1,long long val2) { 23 int newroot = tot++, tmp = newroot; 24 c1[newroot] = c1[root] + val1; 25 c2[newroot] = c2[root] + val2; 26 int l = 1, r = n; 27 while(l < r) { 28 int mid = (l+r)/2; 29 if(pos <= mid) { 30 lson[newroot] = tot++; 31 rson[newroot] = rson[root]; 32 newroot = lson[newroot]; 33 root = lson[root]; 34 r = mid; 35 } else { 36 rson[newroot] = tot++; 37 lson[newroot] = lson[root]; 38 newroot = rson[newroot]; 39 root = rson[root]; 40 l = mid+1; 41 } 42 c1[newroot] = c1[root] + val1; 43 c2[newroot] = c2[root] + val2; 44 } 45 return tmp; 46 } 47 long long query(int root,int K) { 48 long long ret = 0; 49 int l = 1, r = n; 50 while(l < r) { 51 int mid = (l+r)/2; 52 if(c1[lson[root]] >= K) { 53 r = mid; 54 root = lson[root]; 55 } else { 56 K -= c1[lson[root]]; 57 ret += c2[lson[root]]; 58 root = rson[root]; 59 l = mid+1; 60 } 61 } 62 return ret + c2[root]; 63 } 64 struct Node { 65 int x; 66 int D; 67 int index; 68 Node(int _x = 0,int _D = 0,int _index = 0) { 69 x = _x; 70 D = _D; 71 index = _index; 72 } 73 } node[MAXN]; 74 bool cmp(Node a,Node b) { 75 if(a.x != b.x)return a.x < b.x; 76 else return a.D > b.D; 77 } 78 int y[MAXN]; 79 int ind[MAXN]; 80 bool cmp2(int a,int b) { 81 return y[a] < y[b]; 82 } 83 int rind[MAXN]; 84 int main() { 85 int N,MM,X,P; 86 while(~scanf("%d%d%d%d",&N,&MM,&X,&P)) { 87 tot = 0; 88 int cnt = 0; 89 int cnty = 0; 90 int L,R,D; 91 for(int i = 0; i < N; i++) { 92 scanf("%d%d%d",&L,&R,&D); 93 y[cnty++] = D; 94 ind[i] = i; 95 node[++cnt] = Node(L,D,i); 96 node[++cnt] = Node(R,-D,i); 97 } 98 sort(ind,ind+N,cmp2); 99 for(int i = 0; i < N; i++) 100 rind[ind[i]] = i+1; 101 n = N; 102 sort(node+1,node+cnt+1,cmp); 103 T[0] = build(1,n); 104 for(int i = 1; i <= cnt; i++) { 105 if(node[i].D > 0) 106 T[i] = update(T[i-1],rind[node[i].index],1,node[i].D); 107 else 108 T[i] = update(T[i-1],rind[node[i].index],-1,node[i].D); 109 } 110 int x,a,b,c; 111 long long pre = 1; 112 while(MM--) { 113 scanf("%d%d%d%d",&x,&a,&b,&c); 114 int id = 0; 115 int l = 1, r = cnt; 116 while(l <= r) { 117 int mid = (l+r)/2; 118 if(node[mid].x < x || (node[mid].x == x && node[mid].D > 0)) { 119 id = mid; 120 l = mid+1; 121 } else { 122 r = mid-1; 123 } 124 } 125 int K = (pre%c*a%c+b)%c; 126 if(K == 0) { 127 printf("0\n"); 128 pre = 0; 129 continue; 130 } 131 long long ans = query(T[id],K); 132 if(pre > P)ans *= 2; 133 printf("%I64d\n",ans); 134 pre = ans; 135 } 136 } 137 return 0; 138 }
Xor http://acm.hdu.edu.cn/showproblem.php?pid=4867
看不懂的。待补。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 #define lson(x) ((x)<<1) 7 #define rson(x) ((x)<<1|1) 8 typedef long long LL ; 9 const int P = 1000000007 ; 10 const int MAXN = 10001 ; 11 const int MAXLEN = 220; 12 const int MAXM = 10 ; // 0<=x_i<2^30 13 typedef short Node; 14 typedef pair<short,int> CNode; 15 CNode M[ MAXN << 2 ][ MAXLEN ]; 16 int Mlen[ MAXN << 2 ]; 17 int ID[ MAXN ] ; 18 bool one[10]; 19 vector<short> ret; 20 vector<short> split(int n){ //将n化为二进制 ai<=1000 2^10=1024 so 10bit 21 for(int i=0;i<10;i++){ 22 one[i]=(n>>i)&1; //one 二进制逆序的 23 } 24 LL pre=0; 25 ret.clear(); 26 for(int i=9;i>=0;i--){ 27 pre<<=1; 28 if(one[i]){ 29 ret.push_back(pre<<4|i); //四位可以表示10 i<10 30 pre|=1; 31 } 32 } 33 ret.push_back(pre<<4); 34 return ret; 35 } 36 short llen ; 37 inline short merge( short a, short b ) { 38 short ra = a&0xf, rb=b&0xf; 39 short c=max( ra, rb); 40 llen = min(ra,rb); 41 a>>=4; 42 b>>=4; 43 a >>= (c-ra); 44 b >>= (c-rb); 45 return (a^b)<<4|c; 46 } 47 int a[ MAXN ]; 48 int max_size ; 49 CNode tM[ MAXLEN*MAXLEN]; 50 void merge( CNode a[], int alen, CNode b[], int blen, 51 CNode c[], int &k) { 52 k = 0; 53 int tlen = 0; 54 for( int i = 0; i < alen; ++ i) { 55 short pre = a[i].first, now ; 56 LL A = a[i].second; 57 for(int j = 0; j < blen; ++ j) { 58 now = merge( b[j].first, pre ); 59 int B = b[j].second; 60 tM[tlen ++] = make_pair( now, (A *(1<<llen)%P)*B%P); 61 } 62 } 63 sort( tM, tM + tlen ); 64 for(int i=0; i<tlen; ++i) { 65 if(!i || tM[i].first != tM[i-1].first) { 66 c[k++] = tM[i]; 67 } else c[k-1].second = (c[k-1].second + tM[i].second)%P; 68 } 69 } 70 int msz; 71 void build(int x, int l, int r) { 72 int m=(l+r)>>1; 73 Mlen[x] = 0; 74 if(l+1==r) { 75 ID[l]=x; 76 vector< Node > v=split( a[l] ); 77 for(int i = 0; i < v.size(); ++ i) M[ x ][ Mlen[x] ++ ] = make_pair(v[i],1); 78 msz=max(msz,Mlen[x]); 79 return ; 80 } 81 build( lson(x), l, m); 82 build( rson(x), m, r); 83 merge( M[lson(x)], Mlen[lson(x)], M[rson(x)], Mlen[rson(x)], M[x],Mlen[x]); 84 msz=max(msz,Mlen[x]); 85 } 86 void update( int pos, int val ) { 87 vector< Node > v=split( val); 88 a[pos ] =val ; 89 int x = ID[pos ]; 90 Mlen[ x ] = 0; 91 for(int i = 0; i < v.size(); ++ i) M[ x ][ Mlen[ x ] ++ ] = make_pair(v[i],1); 92 for(x >>= 1; x ; x >>= 1) { 93 merge( M[lson(x)], Mlen[lson(x)], M[rson(x)], Mlen[rson(x)], M[x],Mlen[x]); 94 } 95 } 96 int count( int k) { 97 LL ans = 0; 98 for(int i = 0; i < MAXM; ++ i) { 99 Node tar = k<<4|i; 100 int j = lower_bound( M[1], M[1] + Mlen[1], make_pair(tar, -1)) - M[1]; 101 if( j<Mlen[1] && M[1][j].first == tar) { 102 ans += M[ 1 ][ j].second; 103 ans %= P; 104 } 105 k >>= 1; 106 } 107 return (int) ans; 108 } 109 int main() { 110 int n, m,T; 111 cin >> T ; 112 while(T--) { 113 cin >> n >> m; 114 for(int i=0; i<n; ++i) scanf("%d", a + i); 115 build( 1, 0, n ); 116 for(int c=0; c<m; ++c) { 117 char op[ 4 ]; 118 int a, b; 119 scanf("%s", op); 120 if(op[0] == 'C') { 121 scanf("%d%d", &a, &b); 122 update( a, b ); 123 } else { 124 scanf("%d", &a); 125 printf("%d\n", count(a) ); 126 } 127 } 128 } 129 return 0; 130 }
Information Extraction http://acm.hdu.edu.cn/showproblem.php?pid=4868
模拟题。没研究。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N=10010; 5 const int M=35; 6 char html[M][N],stored[M][N],sta1[N][M]; 7 char mapping[M][M][2][M]; 8 int mapNum[M],sta2[N]; 9 void getHTML(int n) { 10 int j,i=0,flag=1; 11 char beginTag[M],tag[M]; 12 getchar(); 13 while(1) { 14 html[n][i]=getchar(); 15 if(html[n][i]=='<') { 16 j=0; 17 while(html[n][++i]=getchar()) { 18 if(html[n][i]=='/')continue; 19 if(html[n][i]==' '||html[n][i]=='>')break; 20 tag[j++]=html[n][i]; 21 } 22 tag[j]='\0'; 23 if(flag==1) { 24 strcpy(beginTag,tag); 25 flag=0; 26 } else if(!strcmp(tag,beginTag)) { 27 html[n][++i]='\0'; 28 return; 29 } 30 } 31 i++; 32 } 33 } 34 void getMapping(int n,int m) { 35 int i,j; 36 char mp[100]; 37 scanf("%s",mp); 38 for(i=0; mp[i]!='-'; i++) 39 mapping[n][m][0][i]=mp[i]; 40 mapping[n][m][0][i]='\0'; 41 for(j=0,i++; i<strlen(mp); i++,j++) 42 mapping[n][m][1][j]=mp[i]; 43 mapping[n][m][1][j]='\0'; 44 } 45 void getTag(int n,int i,char tag[]) { 46 int j=0; 47 while(1) { 48 i++; 49 if(html[n][i]=='/')continue; 50 if(html[n][i]==' '||html[n][i]=='>')break; 51 tag[j++]=html[n][i]; 52 } 53 tag[j]='\0'; 54 } 55 int getId(int n,int i,char id[]) { 56 int j; 57 id[0]='\0'; 58 char tmp[M]; 59 while(html[n][i]==' ') { 60 j=0; 61 while(html[n][++i]!='=') 62 tmp[j++]=html[n][i]; 63 tmp[j]='\0'; 64 if(!strcmp(tmp,"id")) { 65 i++; 66 j=0; 67 while(html[n][++i]!='"') 68 id[j++]=html[n][i]; 69 id[j]='\0'; 70 } else { 71 i++; 72 while(html[n][++i]!='"'); 73 } 74 i++; 75 } 76 return i; 77 } 78 void store(int n,int i,int j,char tag[]) { 79 stored[j][0]='\0'; 80 int k,y=0,flag=0,len=strlen(tag); 81 for(i++;; i++) { 82 k=0; 83 if(html[n][i]=='<') 84 for(; k<len; k++) 85 if(tag[k]!=html[n][i+1+k])break; 86 if(k==len)flag++; 87 k=0; 88 if(html[n][i]=='<'&&html[n][i+1]=='/') 89 for(; k<len; k++) 90 if(tag[k]!=html[n][i+2+k])break; 91 if(k==len) { 92 if(!flag) { 93 stored[j][y]='\0'; 94 return; 95 } else flag--; 96 } 97 stored[j][y++]=html[n][i]; 98 } 99 } 100 bool isStructure(int n,int m) { 101 int i,j,k,ii,flag=0,top=-1; 102 char tag[M],id[M],tag2[M],id2[M]; 103 int len1=strlen(html[n]); 104 for(i=k=0; i<len1;) { 105 ii=i; 106 while(html[n][i]==' '||html[n][i]=='\n')i++; 107 while(html[m][k]!='<')k++; 108 getTag(n,i,tag); 109 getTag(m,k,tag2); 110 if(strcmp(tag,tag2)||html[n][i+1]!=html[m][k+1]) { 111 if(!strcmp(tag,tag2))sta2[top]++; 112 if(!flag) { 113 return false; 114 } 115 while(html[m][k]!='>')k++; 116 i=ii; 117 continue; 118 } 119 if(html[n][i+1]=='/') { //</xx> 120 if(!sta2[top]) { 121 i+=strlen(tag)+3; 122 flag--; 123 } else sta2[top]--; 124 k+=strlen(tag)+3; 125 } else { //<xx>或者<xx/> 126 i+=strlen(tag)+1; 127 k+=strlen(tag2)+1; 128 if(html[n][i]==' ') { //有id 129 if(html[m][k]!=' ') { 130 if(!flag) { 131 return false; 132 } 133 while(html[m][k]!='>')k++; 134 i=ii; 135 continue; 136 } 137 i=getId(n,i,id); 138 k=getId(m,k,id2); 139 if(strcmp(id,id2)) { 140 if(!flag) { 141 return false; 142 } 143 while(html[m][k]!='>')k++; 144 i=ii; 145 continue; 146 } 147 } 148 for(j=0; j<mapNum[n]; j++) 149 if(!strcmp(id,mapping[n][j][0])) 150 break; 151 if(html[n][i]=='/') { //<xx/> 152 i+=2; 153 k+=2; 154 } else { //<xx> 155 if(j!=mapNum[n]) { //需映射的id 156 strcpy(sta1[++top],tag); 157 flag++; 158 sta2[top]=0; 159 for(j=0; j<mapNum[n]; j++) 160 if(!strcmp(id,mapping[n][j][0])) 161 store(m,k,j,tag); 162 } 163 i++; 164 k++; 165 } 166 } 167 } 168 return true; 169 } 170 void output(int n) { 171 int i,j,k,ii; 172 char tag[M]; 173 int len1=strlen(html[0]); 174 for(i=0; i<len1;) { 175 while(i<len1&&html[0][i]!='<') 176 putchar(html[0][i++]); 177 if(i==len1)break; 178 getTag(0,i,tag); 179 for(j=0; j<mapNum[n]; j++) 180 if(!strcmp(tag,mapping[n][j][1])) 181 break; 182 if(j==mapNum[n]) { 183 putchar(html[0][i++]); 184 continue; 185 } else { 186 int len=strlen(tag); 187 ii=i; 188 for(i+=len+1;; i++) { 189 k=0; 190 if(html[0][i]=='<'&&html[0][i+1]=='/') 191 for(; k<len; k++) 192 if(tag[k]!=html[0][i+2+k])break; 193 if(k==len)break; 194 } 195 while(html[0][ii]!='>') 196 putchar(html[0][ii++]); 197 putchar(html[0][ii++]); 198 printf("%s",stored[j]); 199 while(html[0][i]!='>') 200 putchar(html[0][i++]); 201 putchar(html[0][i++]); 202 } 203 } 204 } 205 int main() { 206 int t; 207 while(~scanf("%d",&t)){ 208 int cas=1; 209 while(t--) { 210 int i,j,n,m; 211 getHTML(0); 212 scanf("%d",&n); 213 for(i=1; i<=n; i++) { 214 getHTML(i); 215 scanf("%d",&mapNum[i]); 216 for(j=0; j<mapNum[i]; j++) 217 getMapping(i,j); 218 } 219 getHTML(n+1); 220 printf("Case #%d:\n",cas++); 221 for(i=1; i<=n; i++) 222 if(isStructure(i,n+1)) { 223 output(i); 224 break; 225 } 226 if(i==n+1)printf("Can't Identify\n"); 227 else puts(""); 228 } 229 } 230 return 0; 231 }
Turn the pokers http://acm.hdu.edu.cn/showproblem.php?pid=4869
快速幂求逆元,a%p,p是质数,a逆元是a^(p-2) %p。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 typedef __int64 LL; 5 const int M=100010; 6 const int mod=1000000009; 7 LL Q_pow(LL a,LL n) { 8 LL res=1,tmp=a; 9 while(n) { 10 if(n&1) { 11 res*=tmp; 12 res%=mod; 13 } 14 tmp*=tmp; 15 tmp%=mod; 16 n>>=1; 17 } 18 return res; 19 } 20 LL C[M]; 21 LL INV[M]; 22 int main() { 23 for(int i=1; i<M; i++) { 24 INV[i]=Q_pow(i,mod-2); 25 } 26 int n,m,a; 27 while(~scanf("%d%d",&n,&m)) { 28 C[0]=1; 29 for(int i=1;i<=m;i++){ 30 C[i]=C[i-1]*(m-i+1)%mod*INV[i]%mod; 31 } 32 int L=0,R=0,nl,nr,tmp; 33 for(int i=0;i<n;i++){ 34 scanf("%d",&a); 35 tmp=min(m-L,a); 36 nr=L+tmp-(a-tmp); 37 tmp=min(R,a); 38 nl=R-tmp+(a-tmp); 39 if(nl>nr) swap(nl,nr); 40 if(L<=a&&a<=R){ 41 if(L%2==a%2){ 42 nl=0; 43 } 44 else{ 45 nl=min(nl,1); 46 } 47 } 48 if((m-R)<=a&&a<=(m-L)){ 49 if((m-L)%2==a%2){ 50 nr=m; 51 } 52 else{ 53 nr=max(nr,m-1); 54 } 55 } 56 if(L>=a) nl=min(nl,L-a); 57 if(m-R>=a) nr=max(nr,R+a); 58 L=nl; 59 R=nr; 60 } 61 int ans=0; 62 for(int i=L;i<=R;i+=2){ 63 ans+=C[i]; 64 ans%=mod; 65 } 66 printf("%d\n",ans); 67 } 68 return 0; 69 }
Rating http://acm.hdu.edu.cn/showproblem.php?pid=4870
写出方程,高斯消元。题目意思我们可以推导出一个公式:E(i,j)=p*E(min(i+1,j),max(i+1,j))+(1-p)*E(max(i-2,0),j)+1....(1式)
我们可以将一式进行移项:得到 E(i,j)-p*E(min(i+1,j),max(i+1,j))-(1-p)*E(max(i-2,0),j)=1....(2式)
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 #define mt(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 const int M=420; 8 double a[M][M],x[M];//方程的左边的矩阵和等式右边的值,求解之后x存的就是结果 9 int equ,var; //方程数和未知数个数 10 int Gauss() { //返回0表示无解,1表示有解 11 int i,j,k,col,max_r; 12 for(k=0,col=0; k<equ&&col<var; k++,col++) { 13 max_r=k; 14 for(i=k+1; i<equ; i++) 15 if(fabs(a[i][col])>fabs(a[max_r][col])) 16 max_r=i; 17 if(k!=max_r) { 18 for(j=col; j<var; j++) 19 swap(a[k][j],a[max_r][j]); 20 swap(x[k],x[max_r]); 21 } 22 x[k]/=a[k][col]; 23 for(j=col+1; j<var; j++)a[k][j]/=a[k][col]; 24 a[k][col]=1; 25 for(i=0; i<equ; i++) 26 if(i!=k) { 27 x[i]-=x[k]*a[i][col]; 28 for(j=col+1; j<var; j++)a[i][j]-=a[k][j]*a[i][col]; 29 a[i][col]=0; 30 } 31 } 32 return 1; 33 } 34 int id[22][22]; 35 int main() { 36 int cnt = 0; 37 for(int i = 0; i <= 20; i++) 38 for(int j = 0; j <= 20; j++) { 39 if(i > j)continue; 40 if(i == 20 && j == 20)continue; 41 id[i][j] = cnt++; 42 } 43 equ = var = cnt; 44 double p; 45 while(~scanf("%lf",&p)) { 46 mt(a,0); 47 for(int i = 0; i <= 20; i++) 48 for(int j = 0; j <= 20; j++) { 49 if(i > j)continue; 50 if(i == 20 && j == 20)continue; 51 int u = id[i][j]; 52 a[u][u] = 1.0; 53 if(i == 20 || j == 20) { 54 x[u] = 0.0; 55 continue; 56 } 57 x[u] = 1.0; 58 int nx = i+1; 59 if(nx <= j) 60 a[u][id[nx][j]] -= p; 61 else a[u][id[j][nx]] -= p; 62 nx = max(0,i-2); 63 a[u][id[nx][j]] -= (1-p); 64 } 65 Gauss(); 66 printf("%.6f\n",x[0]); 67 } 68 return 0; 69 }
Shortest-path tree http://acm.hdu.edu.cn/showproblem.php?pid=4871
用dij记录字典序最小的最短路径生成树,存pre里,其他的不懂。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<queue> 5 #define mt(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 const int inf=0x3f3f3f3f; 8 const int M=30010; 9 int pre[M]; 10 int pre_w[M]; 11 class Dijkstra { // µ¥Ô´×î¶Ì·£¨dijkstra£© 12 struct E { 13 int u,v,next,w; 14 } e[M<<2]; 15 struct Q { 16 int id,w; 17 friend bool operator <(Q a,Q b) { 18 return a.w>b.w; 19 } 20 } node; 21 priority_queue<Q> q; 22 int le,head[M],dis[M]; 23 bool used[M]; 24 public: 25 void init() { 26 le=0; 27 mt(head,-1); 28 } 29 int getvalue(int id) { 30 return dis[id]; 31 } 32 void add(int u,int v,int w) { 33 e[le].u=u; 34 e[le].v=v; 35 e[le].w=w; 36 e[le].next=head[u]; 37 head[u]=le++; 38 } 39 void solve(int s) { 40 for(int i=0; i<M; i++) used[i]=true,dis[i]=inf; 41 dis[s]=0; 42 pre[s]=-1; 43 while(!q.empty())q.pop(); 44 node.id=s; 45 node.w=0; 46 q.push(node); 47 while(!q.empty()) { 48 node=q.top(); 49 q.pop(); 50 int u=node.id; 51 if(used[u]) { 52 used[u]=false; 53 for(int i=head[u]; ~i; i=e[i].next) { 54 int v=e[i].v; 55 int w=e[i].w; 56 if(used[v]&&dis[v]>w+dis[u]) { 57 dis[v]=w+dis[u]; 58 node.id=v; 59 node.w=dis[v]; 60 q.push(node); 61 pre[v]=u; 62 pre_w[v]=w; 63 } 64 else if(dis[v]==w+dis[u]&&u<pre[v]){ 65 pre[v]=u; 66 pre_w[v]=w; 67 } 68 } 69 } 70 } 71 } 72 }gx; 73 struct G{ 74 struct E{ 75 int u,v,w,next; 76 }e[M<<1]; 77 int le,head[M]; 78 void init(){ 79 le=0; 80 mt(head,-1); 81 } 82 void add(int u,int v,int w){ 83 e[le].u=u; 84 e[le].v=v; 85 e[le].w=w; 86 e[le].next=head[u]; 87 head[u]=le++; 88 } 89 }g; 90 bool vis[M]; 91 int ans1,ans2; 92 int k; 93 int size[M]; 94 int dfs(int u,int fa) { 95 size[u]=1; 96 for(int i=g.head[u];~i;i=g.e[i].next){ 97 int v=g.e[i].v; 98 if(v!=fa&&!vis[v]){ 99 size[u]+=dfs(v,u); 100 } 101 } 102 return size[u]; 103 } 104 int minn; 105 void getroot(int u,int fa,int totnum,int &root){ 106 int maxx=totnum-size[u]; 107 for(int i=g.head[u];~i;i=g.e[i].next){ 108 int v=g.e[i].v; 109 if(v!=fa&&!vis[v]){ 110 getroot(v,u,totnum,root); 111 maxx=max(maxx,size[v]); 112 } 113 } 114 if(minn>maxx){ 115 minn=maxx; 116 root=u; 117 } 118 } 119 int dp[M]; 120 int dpnum[M]; 121 int pd[M]; 122 int pdnum[M]; 123 int maxdep; 124 void getpd(int u,int fa,int nw,int nd){ 125 if(nd>k-1) return ; 126 maxdep=max(maxdep,nd); 127 if(nw>pd[nd]){ 128 pd[nd]=nw; 129 pdnum[nd]=1; 130 } 131 else if(nw==pd[nd]){ 132 pdnum[nd]++; 133 } 134 for(int i=g.head[u];~i;i=g.e[i].next){ 135 int v=g.e[i].v; 136 if(v!=fa&&!vis[v]){ 137 getpd(v,u,nw+g.e[i].w,nd+1); 138 } 139 } 140 } 141 void solve(int u) { 142 int totnum = dfs(u,-1); 143 minn = inf; 144 int root; 145 getroot(u,-1,totnum,root); 146 vis[root] = true; 147 for(int i = 0; i <= totnum; i++) { 148 dp[i] = 0; 149 dpnum[i] = 0; 150 } 151 dpnum[0] = 1; 152 for(int i = g.head[root]; i != -1; i = g.e[i].next) { 153 int v = g.e[i].v; 154 if(vis[v])continue; 155 maxdep = 0; 156 for(int j = 0; j <= size[v]; j++) { 157 pd[j] = 0; 158 pdnum[j] = 0; 159 } 160 pdnum[0] = 1; 161 getpd(v,u,g.e[i].w,1); 162 for(int j = 1; j <= maxdep && j < k; j++) 163 if(pdnum[j]&&dpnum[k-1-j]) { 164 if(ans1 < pd[j]+dp[k-1-j]) { 165 ans1 = pd[j]+dp[k-1-j]; 166 ans2 = pdnum[j]*dpnum[k-1-j]; 167 } else if(ans1 == pd[j]+dp[k-1-j]) 168 ans2 += pdnum[j]*dpnum[k-1-j]; 169 } 170 for(int j = 1; j <= maxdep && j <= k; j++) { 171 if(dp[j] < pd[j]) { 172 dp[j] = pd[j]; 173 dpnum[j] = pdnum[j]; 174 } else if(dp[j] == pd[j]) 175 dpnum[j] += pdnum[j]; 176 } 177 } 178 for(int i = g.head[root]; i != -1; i = g.e[i].next) { 179 int v = g.e[i].v; 180 if(vis[v])continue; 181 solve(v); 182 } 183 } 184 int main() { 185 int t,n,m,u,v,w; 186 while(~scanf("%d",&t)){ 187 while(t--) { 188 scanf("%d%d%d",&n,&m,&k); 189 gx.init(); 190 while(m--) { 191 scanf("%d%d%d",&u,&v,&w); 192 gx.add(u,v,w); 193 gx.add(v,u,w); 194 } 195 gx.solve(1); 196 g.init(); 197 for(int i = 2; i <= n; i++) { 198 g.add(i,pre[i],pre_w[i]); 199 g.add(pre[i],i,pre_w[i]); 200 } 201 ans1=ans2=0; 202 mt(vis,0); 203 solve(1); 204 printf("%d %d\n",ans1,ans2); 205 } 206 } 207 return 0; 208 }
end