2017暑假第二阶段第四场 总结
来源:互联网 发布:极限挑战网络直播地址 编辑:程序博客网 时间:2024/06/11 05:15
T1 果冻怪
时间限制 1s 空间限制 128MB
问题描述
小南和小开在三友路上养了很多只果冻怪。我们可以将三友路想象成一根长度无限的数 轴,在这上面生活着n只果冻怪。每经过一秒,一只果冻怪便会分裂成两只。具体来说,一 只坐标为x的果冻怪,会分裂成两只分别在(x − 1),(x + 1)上的果冻怪,并且原来在x上的果冻怪会消失。 由于生存空间有限,若一个位置上有不少于P只果冻怪,那么会立刻消失 P 只。经过测 定P = 10^9 + 7。 小南和小开想知道在第T秒末,位置w有多少只果冻怪。初始时刻是0秒初。
输入格式
第一行为三个整数,n,T,w。含义如题所述。
接下来 n 行,每行两个整数xi,ci,表示xi位置,有ci只果冻怪。注意xi可能有重复。
输出格式
输出一个非负整数,表示 T 秒末 w 位置上的果冻怪个数
数据范围
对于 100%的数据:1 ≤ n,T,ci ≤ 10
5 ,0 ≤ |w|,|xi| ≤ 105 。
考虑n个果冻怪,可以看成多个果冻怪的影响相加,那么首先考虑1个果冻怪的情形。画出1个果冻怪的分裂情况,则很容易看出是一个杨辉三角形的形式。结合w、x、T之间的关系不难得出结论。由于需要计算的组合数全部在杨辉三角的同一层,用O(n)的循环预处理出该层组合数即可。
当abs(w-x)与T奇偶性不同时不会增加果冻怪。当w > x+T或w < x-T时不会增加果冻怪。
注意数据规模,不能使用Lucas定理。在这样的规模下Lucas退化成了O(n)的暴力求组合数。容易因为习惯性思维和模质数的条件写成Lucas超时。
#include<stdio.h>#define ll long longconst ll mod=1e9+7;ll Ans,N,T,W,X,Y,C[100005];ll ksm(ll a,ll b){ ll ans=1;a%=mod; while(b) { if(b&1)ans=ans*a%mod; a=a*a%mod;b>>=1; } return ans;}int main(){ int i; ll tmp; scanf("%lld%lld%lld",&N,&T,&W); C[0]=1;C[1]=T; for(i=2;i<=T;i++)C[i]=C[i-1]*(T-i+1)%mod*ksm(i,mod-2)%mod;//预处理 for(i=1;i<=N;i++) { scanf("%lld%lld",&X,&Y); if(W>X)tmp=W-X; else tmp=X-W; if((tmp&1)!=(T&1))continue; if(W>X+T||W<X-T)continue; Ans=(Ans+C[T+1-(((T+2)>>1)+(tmp>>1))]*Y%mod)%mod; } printf("%lld",Ans);}
T2 解密游戏
时间限制 2s 空间限制 384MB
问题描述
小南和小开特别喜欢玩解密游戏,轮到小南加密的时候,由于他的加密方式过于丧心病 狂,所以小开怎么也不能解密成功,于是她来找你帮忙。 密文是一个长度为 n 的数字串,只由 0~9 之间的数字组成。每个小写字母对应 0~9 之 间的一个数字。小南和小开共同拥有一本字典,字典中有 m 个单词,每个单词长度不超过 50。 明文是一个数字,表示最少用多少个单词首尾拼接在一起,使得拼接而成的这个字符串 可以表示密文(也即相同位置的字符串中字母对应数字跟密文相同)。单词可以重复使用。
输出明文,如果无解的话明文为-1。
输入格式
第一行两个正整数 n,m。
第二行有 26 个数字,每个数字是 0~9 之间的数,分别表示字母 a~z 对应的数字。
第三行是长度为 n 的数字串,表示密文。 接下来 m 行,每行一个小写字母串,表示字典中的一个单词。
输出格式
输出一个整数,表示明文
数据范围
对于 30%的数据:1 ≤ n,m ≤ 1000。
对于 100%的数据:1 ≤ n,m ≤ 105 。
注意到本题的空间限制比较大,是其他题目的三倍,再考虑到本题一定会涉及字符串的匹配,那么字典树是比较理想的选择。
显然可以看成背包动规。令f[i]表示解密完前i个字母时的最小单词数,那么显然得到状态转移方程:
那么我们从密文的第一位开始,将i~n之间的字符串在字典树中进行匹配,一边匹配一边更新f数组即可。由于单词长度不超过50,那么字典树的深度最多也是50,所以最多计算50*10
#include<stdio.h>#include<cstring>#define Min(x,y) ((x<y)?(x):(y))int N,M,Hash[500];int f[100005];int rt=1,tot=1,Son[5000005][10];bool num[5000005];//triechar s[100],ask[100005];void Insert(){ int len,i,p=rt,t; scanf("%s",s);len=strlen(s); for(i=0;i<len;i++,p=Son[p][t]) { t=Hash[s[i]]; if(!Son[p][t])Son[p][t]=++tot; } num[p]=true;}void Find(int l){ int p=rt,i,t; for(i=l;i<N&&p;i++,p=Son[p][t]) { t=ask[i]-48; if(num[Son[p][t]])f[i+1]=Min(f[i+1],f[l]+1); }}int main(){ int i; scanf("%d%d",&N,&M); for(i=0;i<26;i++)scanf("%d",&Hash[i+'a']); scanf("%s",ask); for(i=1;i<=M;i++)Insert(); memset(f,60,sizeof(f)); f[0]=0; for(i=1;i<=N;i++)Find(i-1); if(f[N]==f[100001])puts("-1"); else printf("%d",f[N]);}
T3 分割财产
遇到的构造类第一题。比赛时完全没有思路,就写了个比较精巧的骗分,竟然还骗到了90分。下面还是简要介绍一下骗分算法:
首先构造出这样的数列:
再将原数列排序后,用对应位置的差去填充上面的空位即可。这样的骗分可以保证出现
90分骗分代码:
#include<algorithm>#include<stdio.h>using namespace std;int N,data[5005],Hash[5005],Ans[5005][2];int main(){ int i,j=-1; scanf("%d",&N); for(i=1;i<=N;i++)scanf("%d",&data[i]),Hash[i]=data[i]; sort(Hash+1,Hash+N+1); for(i=1;i<=N;i++) { if(i&1)j++; Ans[i][i&1]=Hash[i]-j; Ans[i][i-1&1]=j; } puts("YES"); for(i=1;i<=N;i++) { j=lower_bound(Hash+1,Hash+N+1,data[i])-Hash; printf("%d ",Ans[j][0]); } putchar('\n'); for(i=1;i<=N;i++) { j=lower_bound(Hash+1,Hash+N+1,data[i])-Hash; printf("%d ",Ans[j][1]); }}
正解
将原数列按照大小排序并重新编号,之后分成长度为
设编号为i。
第一段:将i-1赋给ai,将si-ai赋给bi。
第二段:将i-1赋给bi,将si-bi赋给ai。
第三段:将n-i赋给bi,将si-bi赋给ai。
可以看出,ai的第一段与第三段的值是不会重复的,bi的第二段与第三段的值也是不会重复的(
由此也可以看出,这道题无论如何都有解。因此只输出”NO”连一分也不能骗到。
#include<algorithm>#include<stdio.h>using namespace std;int N,S[5005],Hash[5005],A[5005],B[5005];int main(){ int i,j,K; scanf("%d",&N); for(i=1;i<=N;i++)scanf("%d",&S[i]),Hash[i]=S[i]; sort(Hash+1,Hash+N+1); K=(N+2)/3; for(i=1;i<=K;i++) { A[i]=i-1; B[i]=Hash[i]-A[i]; } for(;i<=K*2;i++) { B[i]=i-1; A[i]=Hash[i]-B[i]; } for(;i<=N;i++) { B[i]=N-i; A[i]=Hash[i]-B[i]; } puts("YES"); for(i=1;i<=N;i++) { j=lower_bound(Hash+1,Hash+N+1,S[i])-Hash; printf("%d ",A[j]); } putchar('\n'); for(i=1;i<=N;i++) { j=lower_bound(Hash+1,Hash+N+1,S[i])-Hash; printf("%d ",B[j]); }}
总结
T1是简单的组合数公式;T2是trie+DP,T3是构造。
T1思想江化了,看到组合数模一个质数就想到了Lucas定理,却忽略了时间复杂度导致只得了80分;T2做得不错,只是一开始由于字符数组编号0开始存导致了一些编写上的问题,拖慢了速度;T3的骗分想起来还是比较机智的,以后拿到没见过的题型也要尽量得分。
- 2017暑假第二阶段第四场 总结
- 2017暑假第二阶段第一场 总结
- 2017暑假第二阶段第二场 总结
- 2017暑假第二阶段第三场 总结
- 2017暑假第二阶段第五场 总结
- 2017暑假第二阶段第六场 总结
- 2017暑假第二阶段第七场 总结
- 2017暑假第二阶段第八场 总结
- 2017暑假第二阶段第九场 总结
- 2017暑假训练第四周周中总结
- 2017暑假训练第四周周末总结
- 暑假第四天总结
- BUPT暑假排位第四场
- 暑假集训-个人赛第四场
- 大暑假集训 第二阶段
- CPC23第三场、第四场总结
- 多校赛第三,第四场总结
- 第四场训练赛总结
- Java清空某文件夹内的所有内容
- 性能优化
- 编程题——识别有效的IP地址和掩码并进行分类统计
- Python 字符计数
- 夫妻一方欠的信用卡,属于夫妻共同债务吗?
- 2017暑假第二阶段第四场 总结
- CODE[VS] 1007 级数求和
- 判断是否为第一次登录
- react Input 的defaultValue不随着state变化
- 我读《通过Go来处理每分钟达百万的数据请求》
- 加强版输入输出挂
- 机器学习第七课part2(ROC;AUC;PR曲线)
- main函数之前执行了哪些操作
- android引用anim帧动画导出签名apk报错