【codeforces】【比赛题解】#855 Codefest 17
神秘比赛,以《哈利波特》为主题……有点难。
C题我熬夜切终于是写出来了,可惜比赛结束了,气啊。
比赛链接:点我。
【A】汤姆·里德尔的日记
题意:
哈利波特正在摧毁神秘人的分灵体(魂器)。第一个他见到的魂器是在密室中的日记本,现在这本日记令金妮打开了密室。
哈利波特想要知道哪些人没有被日记施魔,以确保他们不会被日记影响。
哈利波特有一个名单,依次记录了那些被日记本施魔的人,对于每个人,他想知道这个人的名字在之前有没有出现过。
如果第\(i\)个字符串之前有相同的字符串,那么输出"YES",否则输出"NO"。
输入:
第一行,一个正整数\(n(1\leq n\leq100)\)——名单中的字符串数量。
接下来\(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]!='\0'&&str[j][k]!='\0';++k){ 12 if(str[j][k]!=str[i][k]) {o=0; break;} 13 } 14 if((str[i][k]=='\0'&&str[j][k]!='\0')||(str[j][k]=='\0'&&str[i][k]!='\0')) 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\)是\(p\cdot a_{i}+q\cdot a_{j}+r\cdot a_{k}\)的最大值,其中\(1\leq i\leq j\leq k\leq n\)。
帮助斯内普教授计算\(x\)的值,注意,\(x\)可能是负数。
输入:
第一行,四个数,\(n,p,q,r(-10^9\leq p,q,r\leq10^9,1\leq n\leq10^5)\)。
第二行,\(n\)个数,表示\(a_{1},a_{2},\cdots,a_{n}(-10^9\leq 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(1\leq n\leq10^5,1\leq m\leq10^9)\),表示金柜的数量,即树中的节点数,和金柜的型号范围。
接下来\(n-1\)行,每行两个正整数\(u_{i},v_{i}(1\leq u_{i},v_{i}\leq n)\),表示第\(i\)条边,表示了金柜\(u_{i},v_{i}\)之间有连边。保证给定图是一棵树。
接下来一行,两个正整数\(k,x(1\leq k\leq m,1\leq x\leq10)\),表示最高安全的金库的型号和最高安全的金库的最多个数。
输出:
输出一个非负整数,表示方案数对\(10^9+7\)取模的结果。
题解:
这题难度较大,适合做提高组练习……
考虑树形DP,用\(f[i][j][x\!=\!0\!/1\!/2]\)表示在以\(i\)为根的子树中,有\(j\)个最高安全的金柜,而金柜\(i\)的型号是\(\left\{\begin{matrix}x\!=\!0&1\leq type<k\\x\!=\!1&type=k\\x\!=\!2&k<type\leq m\end{matrix}\right.\)。
转移方程如下:\(\begin{matrix}f[i][j][0]=&\left(k-1\right)\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]\right)\\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]\right)\\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]\right)\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)\n",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\n",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 }
而学长的就画风清奇,看上去舒服至极,我实在是自愧不如。
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\n",ans); 58 return 0; 59 }
【D】【E】【F】目前不会。