【codeforces】【比赛题解】#855 Codefest 17

神秘比赛,以《哈利波特》为主题……有点难。

C题我熬夜切终于是写出来了,可惜比赛结束了,气啊。

比赛链接:点我

【A】汤姆·里德尔的日记

题意:

哈利波特正在摧毁神秘人的分灵体(魂器)。第一个他见到的魂器是在密室中的日记本,现在这本日记令金妮打开了密室。

哈利波特想要知道哪些人没有被日记施魔,以确保他们不会被日记影响。

哈利波特有一个名单,依次记录了那些被日记本施魔的人,对于每个人,他想知道这个人的名字在之前有没有出现过。

如果第(i)个字符串之前有相同的字符串,那么输出"YES",否则输出"NO"。

输入:

第一行,一个正整数(n(1leq nleq100))——名单中的字符串数量。

接下来(n)行,每行一个字符串,长度在(1)到(100)之间。

输出:

对于每个字符串,判断它在之前有没有出现过。

题解:

暴力判,你也可以扔到set里面查找,甚至建一棵trie树,我反正暴力判,其实用set写的更方便。

 1 #include<cstdio>
 2 int n;
 3 char str[105][105];
 4 int main(){
 5     scanf("%d",&n);
 6     for(int i=1;i<=n;++i){
 7         scanf("%s",str[i]);
 8         int ok=0;
 9         for(int j=1;j<i;++j){
10             int o=1,k;
11             for(k=0;str[i][k]!=''&&str[j][k]!='';++k){
12                 if(str[j][k]!=str[i][k]) {o=0; break;}
13             }
14             if((str[i][k]==''&&str[j][k]!='')||(str[j][k]==''&&str[i][k]!='')) o=0;
15             if(o==1) {ok=1; break;}
16         }
17         if(ok==1) puts("Yes");
18         else puts("No");
19     }
20     return 0;
21 }

【B】马沃罗·冈特的戒指

题意:

邓布利多教授正在帮助哈利摧毁分灵体。他侦测到了一个分灵体在冈特家,于是他去了那儿。他看到了马沃罗·冈特的戒指,并认定那是一个分灵体。虽然他摧毁了分灵体,但是自己也身中了黑魔法诅咒。斯内普教授正帮助邓布利多消除诅咒,他需要给邓布利多滴正好(x)滴药水,(x)的计算方法如下:

(x)是(pcdot a_{i}+qcdot a_{j}+rcdot a_{k})的最大值,其中(1leq ileq jleq kleq n)。

帮助斯内普教授计算(x)的值,注意,(x)可能是负数。

输入:

第一行,四个数,(n,p,q,r(-10^9leq p,q,rleq10^9,1leq nleq10^5))。

第二行,(n)个数,表示(a_{1},a_{2},cdots,a_{n}(-10^9leq a_{i}leq10^9))。

输出:

输出(x)。

题解:

枚举(j),通过(p)的正负性算出(i),通过(r)的正负性算出(k)。

 1 #include<cstdio>
 2 int n,p,q,r,a[100005],min1[100005],max1[100005],min2[100005],max2[100005];
 3 long long ans=-3100000000000000000ll;
 4 inline int Min(int x,int y){return x<y?x:y;}
 5 inline int Max(int x,int y){return x>y?x:y;}
 6 int main(){
 7     scanf("%d%d%d%d",&n,&p,&q,&r);
 8     for(int i=1;i<=n;++i) scanf("%d",a+i);
 9     for(int i=0;i<=n+1;++i) min1[i]=min2[i]=2147483647, max1[i]=max2[i]=-2147483647;
10     for(int i=1;i<=n;++i) min1[i]=Min(min1[i-1],a[i]), max1[i]=Max(max1[i-1],a[i]);
11     for(int i=n;i>=1;--i) min2[i]=Min(min2[i+1],a[i]), max2[i]=Max(max2[i+1],a[i]);
12     for(int j=1;j<=n;++j){
13         long long sum=1ll*q*a[j];
14         if(p>0) sum+=1ll*p*max1[j];
15         else sum+=1ll*p*min1[j];
16         if(r>0) sum+=1ll*r*max2[j];
17         else sum+=1ll*r*min2[j];
18         if(ans<sum) ans=sum;
19     }
20     printf("%I64d",ans);
21     return 0;
22 }

【C】赫尔加·赫奇帕奇的金杯

题意:

哈利,罗恩和赫敏发现赫尔加·赫奇帕奇的金杯是一个分灵体。通过赫敏与贝拉特里克斯·莱斯特兰奇的遭遇,她知道了金杯被存放在古灵阁巫师银行中的贝拉特里克斯的金柜中。

古灵阁可以看做是有着(n)个金柜的一棵树,每个金柜有一个型号,范围在(1)到(m)之中。

最高安全的金柜的型号为(k),并且所有型号为(k)的金柜都是最高安全的。

最多有(x)个金柜是最高安全的

另:如果一个金柜是最高安全的,那么与它直接相连的所有金柜都不是最高安全的,且它们的型号一定小于(k)

哈利想知道所有的金柜型号的可能性,这样他能规划出去到贝拉特里克斯的金柜的最佳路线。所以,你需要告诉他,给定古灵阁的结构,所有可能的金柜型号总数。

输入:

第一行,两个正整数(n,m(1leq nleq10^5,1leq mleq10^9)),表示金柜的数量,即树中的节点数,和金柜的型号范围。

接下来(n-1)行,每行两个正整数(u_{i},v_{i}(1leq u_{i},v_{i}leq n)),表示第(i)条边,表示了金柜(u_{i},v_{i})之间有连边。保证给定图是一棵树。

接下来一行,两个正整数(k,x(1leq kleq m,1leq xleq10)),表示最高安全的金库的型号和最高安全的金库的最多个数。

输出:

输出一个非负整数,表示方案数对(10^9+7)取模的结果。

题解:

这题难度较大,适合做提高组练习……

考虑树形DP,用(f[i][j][x!=!0!/1!/2])表示在以(i)为根的子树中,有(j)个最高安全的金柜,而金柜(i)的型号是(left{egin{matrix}x!=!0&1leq type<k\x!=!1&type=k\x!=!2&k<typeleq mend{matrix} ight.)。

转移方程如下:(egin{matrix}f[i][j][0]=&left(k-1 ight)sum_{j_{1}+j_{2}+cdots+j_{i.sons}=j}left(prod_{k=1}^{i.sons}f[i.son_k][j_k][0]+f[i.son_k][j_k][1]+f[i.son_k][j_k][2] ight)\f[i][j][1]=&sum_{j_{1}+j_{2}+cdots+j_{i.sons}=j-1}left(prod_{k=1}^{i.sons}f[i.son_k][j_k][0] ight)\f[i][j][2]=&(m-k)sum_{j_{1}+j_{2}+cdots+j_{i.sons}=j}left(prod_{k=1}^{i.sons}f[i.son_k][j_k][0]+f[i.son_k][j_k][2] ight)end{matrix})。

直接转移比较困难,我选择了左孩子右兄弟,然后再分别处理,导致代码其丑无比,不想拿出来看……

 1 #include<cstdio>
 2 const int Mod=1000000007;
 3 int n,m,k,X,left[100005],rr[100005],right[100005],dp[100005][12][4];
 4 int h[100005],to[200005],nxt[200005],tot=0;
 5 int vis[100005];
 6 inline void Ins(int x,int y){nxt[++tot]=h[x]; to[tot]=y; h[x]=tot;}
 7 inline void ins(int x,int y){
 8     if(!left[x]) left[x]=y, rr[x]=y;
 9     else right[rr[x]]=y, rr[x]=y;
10 }
11 void dfs1(int u){
12     vis[u]=1;
13     for(int i=h[u];i;i=nxt[i]){
14         if(vis[to[i]]) continue;
15         ins(u,to[i]); dfs1(to[i]);
16     }
17 }
18 void dfs2(int u){
19     if(left[u]) dfs2(left[u]);
20     if(right[u]) dfs2(right[u]);
21     if(left[u]){
22         if(right[u]){
23             dp[u][0][0]=((long long)(k-1)*(dp[left[u]][0][0]+dp[left[u]][0][2])%Mod)*dp[right[u]][0][0]%Mod;
24             dp[u][0][2]=(((long long)(m-k)*(dp[left[u]][0][0]+dp[left[u]][0][2])%Mod)*(dp[right[u]][0][0]+dp[right[u]][0][2])+
25                             ((long long)(k-1)*(dp[left[u]][0][0]+dp[left[u]][0][2])%Mod)*dp[right[u]][0][2])%Mod;
26             for(int x=1;x<=X;++x){
27                 for(int y=0;y<=x;++y)
28                     dp[u][x][0]=(dp[u][x][0]+
29                                     ((long long)(k-1)*((long long)dp[left[u]][y][0]+dp[left[u]][y][1]+dp[left[u]][y][2]))%Mod*
30                                     dp[right[u]][x-y][0])%Mod;
31                 for(int y=0;y<=x-1;++y)
32                     dp[u][x][1]=(dp[u][x][1]+
33                         (long long)dp[left[u]][y][0]*((long long)dp[right[u]][x-y-1][0]+dp[right[u]][x-y-1][1]+dp[right[u]][x-y-1][2]))%Mod;
34                 for(int y=0;y<=x;++y)
35                     dp[u][x][1]=(dp[u][x][1]+
36                         ((long long)(k-1)*((long long)dp[left[u]][y][0]+dp[left[u]][y][1]+dp[left[u]][y][2]))%Mod*
37                         dp[right[u]][x-y][1]%Mod+
38                         ((long long)(m-k)*(dp[left[u]][y][0]+dp[left[u]][y][2]))%Mod*dp[right[u]][x-y][1]%Mod)%Mod;
39                 for(int y=0;y<=x;++y)
40                     dp[u][x][2]=(dp[u][x][2]+
41                         ((long long)(k-1)*((long long)dp[left[u]][y][0]+dp[left[u]][y][1]+dp[left[u]][y][2]))%Mod*
42                         dp[right[u]][x-y][2]%Mod+
43                         ((long long)(m-k)*(dp[left[u]][y][0]+dp[left[u]][y][2]))%Mod*(dp[right[u]][x-y][0]+dp[right[u]][x-y][2])%Mod)%Mod;
44             }
45         }
46         else{
47             dp[u][0][0]=(long long)(k-1)*(dp[left[u]][0][0]+dp[left[u]][0][2])%Mod;
48             dp[u][0][2]=(long long)(m-k)*(dp[left[u]][0][0]+dp[left[u]][0][2])%Mod;
49             for(int x=1;x<=X;++x){
50                 dp[u][x][0]=(long long)(k-1)*((long long)dp[left[u]][x][0]+dp[left[u]][x][1]+dp[left[u]][x][2])%Mod;
51                 dp[u][x][1]=dp[left[u]][x-1][0];
52                 dp[u][x][2]=(long long)(m-k)*(dp[left[u]][x][0]+dp[left[u]][x][2])%Mod;
53             }
54         }
55     }
56     else{
57         if(right[u]){
58             dp[u][0][0]=(long long)(k-1)*dp[right[u]][0][0]%Mod;
59             dp[u][0][2]=((long long)(m-k)*(dp[right[u]][0][0]+dp[right[u]][0][2])+(long long)(k-1)*dp[right[u]][0][2])%Mod;
60             for(int x=1;x<=X;++x){
61                 dp[u][x][0]=(long long)(k-1)*dp[right[u]][x][0]%Mod;
62                 dp[u][x][1]=((long long)dp[right[u]][x-1][0]+dp[right[u]][x-1][1]+dp[right[u]][x-1][2]+
63                                 (long long)(m-1)*dp[right[u]][x][1])%Mod;
64                 dp[u][x][2]=((long long)(m-k)*(dp[right[u]][x][0]+dp[right[u]][x][2])+(long long)(k-1)*dp[right[u]][x][2])%Mod;
65             }
66         }
67         else{
68             dp[u][0][0]=k-1;
69             dp[u][1][1]=1;
70             dp[u][0][2]=m-k;
71         }
72     }
73 }
74 int main(){
75     scanf("%d%d",&n,&m);
76     for(int i=1,x,y;i<n;++i) scanf("%d%d",&x,&y), Ins(x,y), Ins(y,x);
77     scanf("%d%d",&k,&X);
78     dfs1(1);
79     dfs2(1);
80 /*    for(int i=1;i<=n;++i) printf("(%d,%d)
",left[i],right[i]);
81     for(int i=1;i<=n;++i){
82         for(int j=0;j<=X;++j){
83             printf("%d, %d : %d, %d, %d
",i,j,dp[i][j][0],dp[i][j][1],dp[i][j][2]);
84         }
85     }*/
86     long long Ans=0;
87     for(int i=0;i<=X;++i) Ans+=(long long)dp[1][i][0]+dp[1][i][1]+dp[1][i][2];
88     printf("%I64d",Ans%Mod);
89     return 0;
90 }
View Code

而学长的就画风清奇,看上去舒服至极,我实在是自愧不如。

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<vector>
 5 #include<cstdio>
 6 #include<queue>
 7 #include<map>
 8 #include<set>
 9 #define MN 100000
10 #define mod 1000000007
11 using namespace std;
12 inline int read()
13 {
14     int x=0,f=1;char ch=getchar();
15     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
16     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
17     return x*f;
18 }
19 int f[MN+5][11],F[MN+5][11],s[MN+5][11],S[MN+5][11],l[MN+5][11],L[MN+5][11],n,K,m,Mx,cnt=0,head[MN+5];
20 struct edge{int to,next;}e[MN*2+5];
21 inline void ins(int f,int t)
22 {
23     e[++cnt]=(edge){t,head[f]};head[f]=cnt;
24     e[++cnt]=(edge){f,head[t]};head[t]=cnt;
25 }
26 inline void R(int&x,int y){x+=y;x>=mod?x-=mod:0;}
27 void Dp(int x,int fa)
28 {
29     f[x][1]=1;s[x][0]=K-1;l[x][0]=m-K;
30     for(int i=head[x];i;i=e[i].next)
31         if(e[i].to!=fa)
32         {
33             Dp(e[i].to,x);
34             for(int j=0;j<=Mx;++j)
35                 for(int k=0;k+j<=Mx;++k)
36                 {
37                     R(F[x][j+k],1LL*f[x][j]*s[e[i].to][k]%mod);
38                     R(S[x][j+k],1LL*s[x][j]*((f[e[i].to][k]+s[e[i].to][k])%mod+l[e[i].to][k])%mod);
39                     R(L[x][j+k],1LL*l[x][j]*(s[e[i].to][k]+l[e[i].to][k])%mod);
40                 }
41             for(int j=0;j<=Mx;++j)
42             {
43                 f[x][j]=F[x][j],F[x][j]=0;
44                 s[x][j]=S[x][j],S[x][j]=0;
45                 l[x][j]=L[x][j],L[x][j]=0;
46             }
47         }
48 }
49 
50 int main()
51 {
52     n=read();m=read();
53     for(int i=1;i<n;++i) ins(read(),read());
54     K=read();Mx=read();
55     Dp(1,0);int ans=0;
56     for(int i=0;i<=Mx;++i) R(ans,f[1][i]),R(ans,l[1][i]),R(ans,s[1][i]);
57     printf("%d
",ans);
58     return 0;
59 }

【D】【E】【F】目前不会。

原文地址:https://www.cnblogs.com/PinkRabbit/p/7664323.html